Skip to content

Conversation

@AmanVarshney01
Copy link
Owner

@AmanVarshney01 AmanVarshney01 commented Dec 23, 2025

Summary by CodeRabbit

  • New Features

    • Platform-specific CLI binaries and per-platform npm packages (darwin/linux/windows).
    • New interactive TUI for guided project setup (renderTui) plus a stable programmatic create() API and launcher that runs the matching platform binary.
    • TUI components, in-app logger, and programmatic options for database/addon setup.
  • Bug Fixes & Improvements

    • Expanded CI/release: multi‑platform build/publish, preview & push preview workflows, GitHub Release artifacts, increased timeouts, and updated preview/release summaries and install instructions.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
create-better-t-stack-web Ready Ready Preview, Comment Dec 24, 2025 10:47am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

📝 Walkthrough

Walkthrough

Adds Bun-based CLI build/publish tooling with per-platform binaries and a launcher; migrates subprocesses from execa to Bun’s $ runtime; replaces many interactive prompt modules with an option-driven API and a TUI; updates CI workflows to build/publish platform packages and release artifacts.

Changes

Cohort / File(s) Summary
CI / Release Workflows
/.github/workflows/pr-preview.yaml, /.github/workflows/pr-preview-push.yaml, /.github/workflows/release.yaml
Add workflow_dispatch inputs and pr/ref fallbacks, increase timeouts, derive preview versions, build & publish per-platform CLI packages, update concurrency/commenting, and upload CLI binaries to GitHub Release.
Platform launcher
apps/cli/bin/create-better-t-stack
New shim executable that locates and spawns platform-specific CLI binaries in node_modules, supports env override, forwards exit codes, and prints actionable error when missing.
Build & Publish scripts
apps/cli/scripts/build.ts, apps/cli/scripts/publish.ts
New Bun-based build producing platform binaries and dist packages; publish orchestrator performs smoke tests, publishes platform packages and main CLI (updates optionalDependencies), supports --dry-run/--tag, and cleans artifacts.
CLI package metadata & config
apps/cli/package.json, apps/cli/tsconfig.json, (removed) apps/cli/tsdown.config.ts
Move entrypoints to src/bin, set bin to launcher, include bin/src in files, add optionalDependencies for platform packages, switch scripts to Bun, enable JSX/TSX, and remove tsdown config.
CLI entry / Programmatic API / TUI
apps/cli/src/cli.ts, apps/cli/src/api.ts, apps/cli/src/index.ts, apps/cli/src/tui/...
Replace legacy CLI wiring with Commander-based entry and exported programmatic create(options) API; add a full TUI implementation (renderTui), many TUI components, hooks, steps config, and theme.
Execution runtime migration
apps/cli/src/helpers/..., apps/cli/src/utils/...
Replace execa calls and clack prompts with Bun’s $ API and new internal logger; adapt .text()/.cwd() usage and error logging across many helpers and utilities.
Database/provider flows → option-driven
apps/cli/src/helpers/database-providers/*
Convert interactive DB setup flows into option-driven APIs (added *SetupOptions types) and propagate mode/options through db setup orchestration.
Prompts & old handlers removed
apps/cli/src/prompts/*, apps/cli/src/helpers/core/command-handlers.ts
Remove many prompt modules and legacy command-handlers; project creation flows migrated into the programmatic API and the new TUI.
Project directory & DB setup helpers
apps/cli/src/utils/project-directory.ts, apps/cli/src/helpers/core/db-setup.ts
Introduce DirectoryConflictAction/DirectoryConflictOptions and DbSetupOptions; convert interactive conflict handling and DB setup signatures to option-driven forms.
Logger, TUI hooks & components
apps/cli/src/utils/logger.ts, apps/cli/src/tui/use-logger.ts, apps/cli/src/tui/components/*, apps/cli/src/tui/steps.ts, apps/cli/src/tui/theme.ts
Add Logger singleton with LogEntry/LogLevel types and log API; add hooks (useLogger/useLatestLog), many TUI components (logo, spinner, prompts, status-bar, log-display), steps config, and theme constants.
Utilities & small public API changes
apps/cli/src/utils/{errors,file-formatter,get-latest-cli-version,open-url,command-exists,docker-utils}.ts, apps/cli/test/test-utils.ts
Add CLIError/CancelledError, make formatFile a no-op, add compile-time CLI_VERSION support, migrate open-url/docker/command checks to Bun, and update tests to use the programmatic create() API and new types.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant GH as GitHub Actions
  participant Repo as Repository
  participant Build as build.ts
  participant Publish as publish.ts
  participant NPM as npm Registry
  participant Release as GitHub Release

  Note over GH,Repo: PR preview / push / release triggers
  GH->>Repo: checkout (PR head SHA or inputs.ref)
  GH->>Build: invoke platform builds
  Build->>Build: compile Bun binaries per-target, create dist/<pkg>/bin + package.json
  Build-->>GH: return builtPackages metadata
  GH->>Publish: run publish.ts (version, tag, builtPackages)
  Publish->>Publish: smoke-test current platform binary
  Publish->>NPM: npm publish per-platform packages (with tag)
  Publish->>NPM: npm publish main CLI package (updates optionalDependencies)
  Publish->>Release: upload zips/tarballs to GitHub Release
  NPM-->>GH: publish confirmations
  Release-->>GH: artifacts available
  GH-->>Repo: post PR/commit comment with preview/release summary
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

preview

"A rabbit in a binary hat,
I hopped through Bun and built each stat.
Binaries packed for every land,
TUI and API, paw in hand.
Publish done — I take a bow and scat!" 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.16% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'EXPERIMENTAL: opentui rewrite' is vague and generic, using the non-descriptive term 'opentui rewrite' without conveying the primary scope or impact of the changeset. Replace with a more specific title that captures the main change, such as 'Migrate CLI to Bun runtime and OpenTUI-based TUI' or 'Replace execa/clack with Bun and implement interactive TUI'. Current title lacks sufficient detail for scanning git history.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bun-compile-opentui

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd6d873 and 57b2f37.

📒 Files selected for processing (2)
  • apps/cli/bin/create-better-t-stack
  • apps/cli/src/constants.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/cli/bin/create-better-t-stack
  • apps/cli/src/constants.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

PR Preview Release

A preview version has been published for this PR.

Package Version NPM Tag
create-better-t-stack 3.11.0-pr750.6c25d46 pr750
create-bts 3.11.0-pr750.6c25d46 pr750
@better-t-stack/types 3.11.0-pr750.6c25d46 pr750

Commit: 6c25d46

Install

# Using the PR tag (always gets latest for this PR)
bunx create-better-t-stack@pr750
npx create-better-t-stack@pr750

# Using exact version
bunx [email protected]
npx [email protected]

# Using the alias
bunx create-bts@pr750
npx create-bts@pr750

NPM Links


To publish a new preview after more commits, remove and re-add the preview label.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (1)
apps/cli/src/utils/errors.ts (1)

1-1: Pipeline failure: Missing dependency consola.

Same issue as install-dependencies.ts - ensure dependencies are properly installed before build. This was already flagged for the other file; verify the package.json includes these dependencies.

🧹 Nitpick comments (17)
apps/cli/src/utils/docker-utils.ts (1)

11-18: Migration to Bun's $ syntax looks correct.

The function properly uses Bun.$ with .quiet() to suppress output, and the error handling correctly returns false when the command fails.

Optional: Add timeout for better reliability

Consider adding a timeout to prevent hanging if the Docker daemon is unresponsive:

 export async function isDockerRunning() {
   try {
-    await $`docker info`.quiet();
+    await $`docker info`.timeout(5000).quiet();
     return true;
   } catch {
     return false;
   }
 }

This ensures the check fails fast rather than hanging indefinitely.

Based on learnings, this correctly uses Bun.$ template literal syntax instead of execa.

apps/cli/src/helpers/core/git.ts (1)

21-22: Consider adding explicit error handling for consistency.

While the current implementation works correctly, lines 21-22 don't use .nothrow() like the earlier git commands, creating an inconsistency in error handling. If git add or git commit fail (e.g., missing git user configuration), the default exception will be thrown.

For better CLI user experience and consistency with the pattern established on lines 8-19, consider adding explicit error handling with helpful messages.

🔎 Proposed refactor for consistent error handling
-  await $`git add -A`.cwd(projectDir).quiet();
-  await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
+  const addResult = await $`git add -A`.cwd(projectDir).nothrow().quiet();
+  if (addResult.exitCode !== 0) {
+    throw new Error(`Failed to stage files: ${addResult.stderr.toString()}`);
+  }
+
+  const commitResult = await $`git commit -m ${"initial commit"}`.cwd(projectDir).nothrow().quiet();
+  if (commitResult.exitCode !== 0) {
+    throw new Error(`Failed to create initial commit: ${commitResult.stderr.toString()}`);
+  }
apps/cli/src/utils/file-formatter.ts (1)

7-7: Consider removing explicit return type per coding guidelines.

The coding guidelines indicate not to use explicit return types in TypeScript files.

🔎 Proposed fix
-export async function formatFile(_filePath: string, content: string): Promise<string | null> {
+export async function formatFile(_filePath: string, content: string) {
apps/cli/src/constants.ts (2)

22-39: Consider security implications of directory traversal.

The findMainPackage() function traverses up the directory tree without a maximum depth limit, which could potentially traverse the entire filesystem if node_modules is never found. While this is unlikely to be exploitable, it could cause performance issues.

🔎 Add a maximum depth limit
 function findMainPackage(): string | null {
   // Use process.execPath to get actual filesystem path (Bun.main returns bunfs virtual path)
   let current = path.dirname(process.execPath);
+  let depth = 0;
+  const MAX_DEPTH = 20; // Reasonable limit for filesystem traversal
 
   // Search up the directory tree for node_modules/create-better-t-stack
   while (current !== path.dirname(current)) {
+    if (depth++ > MAX_DEPTH) break;
     const candidate = path.join(current, "node_modules", "create-better-t-stack");
     const templatesPath = path.join(candidate, "templates");
 
     if (fs.existsSync(templatesPath)) {
       return candidate;
     }
 
     current = path.dirname(current);
   }
 
   return null;
 }

46-82: Simplify complex fallback logic with early returns.

The getPkgRoot() function has 4 different fallback strategies with deep nesting. This complexity makes it harder to understand and maintain. The multiple fs.existsSync checks without error handling could also fail silently in edge cases.

🔎 Refactor for clarity

Consider extracting each fallback strategy into separate helper functions:

function tryMainPackage(): string | null {
  const mainPkg = findMainPackage();
  return mainPkg || null;
}

function tryDevBinaryPath(binaryPath: string): string | null {
  const binaryDir = path.dirname(binaryPath);
  const devTemplatesPath = path.resolve(binaryDir, "..", "..", "..", "templates");
  if (fs.existsSync(devTemplatesPath)) {
    return path.resolve(binaryDir, "..", "..", "..");
  }
  return null;
}

function tryAltBinaryPath(binaryPath: string): string | null {
  const binaryDir = path.dirname(binaryPath);
  const altTemplatesPath = path.resolve(binaryDir, "..", "..", "templates");
  if (fs.existsSync(altTemplatesPath)) {
    return path.resolve(binaryDir, "..", "..");
  }
  return null;
}

function trySimpleBinaryPath(binaryPath: string): string | null {
  const binaryDir = path.dirname(binaryPath);
  const simpleTemplatesPath = path.resolve(binaryDir, "..", "templates");
  if (fs.existsSync(simpleTemplatesPath)) {
    return path.resolve(binaryDir, "..");
  }
  return null;
}

function getPkgRoot(): string {
  if (isCompiledBinary()) {
    const binaryPath = process.execPath;
    
    return tryMainPackage() 
      || tryDevBinaryPath(binaryPath)
      || tryAltBinaryPath(binaryPath)
      || trySimpleBinaryPath(binaryPath)
      || getJsModePkgRoot();
  }
  
  return getJsModePkgRoot();
}

function getJsModePkgRoot(): string {
  const __filename = fileURLToPath(import.meta.url);
  const distPath = path.dirname(__filename);
  return path.join(distPath, "../");
}
apps/cli/bin/create-better-t-stack (1)

68-86: Add maximum depth limit to prevent unbounded directory traversal.

Similar to the issue in constants.ts, the findBinary() function traverses up the directory tree without a maximum depth limit, which could cause performance issues if node_modules is never found.

🔎 Add traversal depth limit
 function findBinary(startDir) {
     let current = startDir;
+    let depth = 0;
+    const MAX_DEPTH = 20;
     for (; ;) {
+        if (depth++ > MAX_DEPTH) {
+            return;
+        }
         const modules = join(current, "node_modules");
         if (existsSync(modules)) {
             // Check for scoped package: node_modules/@better-t-stack/cli-{platform}-{arch}
             const scopedPath = join(modules, "@better-t-stack", "cli-" + platform + "-" + arch);
             const candidate = join(scopedPath, "bin", binary);
             if (existsSync(candidate)) {
                 return candidate;
             }
         }
         const parent = dirname(current);
         if (parent === current) {
             return;
         }
         current = parent;
     }
 }
apps/cli/src/utils/get-latest-cli-version.ts (1)

13-27: Consider logging when falling back to default version.

The function silently falls back to "1.0.0" when it fails to read package.json. This could make debugging difficult in production if the package structure is unexpected. Consider adding a debug log or warning.

🔎 Add logging for fallback
 export const getLatestCLIVersion = (): string => {
   // Check if version was embedded at compile time
   if (typeof CLI_VERSION !== "undefined") {
     return CLI_VERSION;
   }
 
   // Fallback to reading package.json (for npm distribution)
   try {
     const packageJsonPath = path.join(PKG_ROOT, "package.json");
     const packageJsonContent = fs.readJSONSync(packageJsonPath);
     return packageJsonContent.version ?? "1.0.0";
   } catch {
+    console.warn("Failed to read CLI version from package.json, using default 1.0.0");
     return "1.0.0";
   }
 };
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

78-81: Remove unnecessary type annotations.

The type annotations on the map callback parameters are redundant since TypeScript can infer them from the array type. This makes the code more verbose without adding value.

🔎 Simplify type annotations
-    const groups = lines.slice(1).map((line: string) => {
+    const groups = lines.slice(1).map((line) => {
       const [name, locations, version, status] = line.trim().split(/\s{2,}/);
       return { name, locations, version, status };
     });

And similarly for line 104:

-  const groupOptions = groups.map((group: { name: string; locations: string }) => ({
+  const groupOptions = groups.map((group) => ({
     value: group.name,
     label: `${group.name} (${group.locations})`,
   }));
.github/workflows/pr-preview.yaml (1)

93-106: Consider adding error handling for individual package publish failures.

The loop publishes each platform package but doesn't handle partial failures gracefully. If one platform package fails to publish, subsequent packages won't be attempted due to shell's default behavior with bun publish failing.

🔎 Proposed fix to continue on individual failures
       - name: Publish CLI platform packages to NPM
         run: |
           cd apps/cli/dist
           ls -la
           for dir in */; do
             if [ -f "$dir/package.json" ]; then
               echo "Publishing $dir..."
               cd "$dir"
-              bun publish --access public --tag ${{ steps.version.outputs.tag }}
+              bun publish --access public --tag ${{ steps.version.outputs.tag }} || echo "Warning: Failed to publish $dir"
               cd ..
             fi
           done
         env:
           NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
apps/cli/src/cli.ts (3)

9-13: Remove unused imports.

The following imports are not used in this file:

  • createProject (line 9) - only used inside the TUI callback, already available from the TUI module
  • getDefaultConfig (line 10) - not referenced
  • path (line 13) - not referenced
🔎 Proposed fix
 import { Command } from "commander";
 import { renderTui } from "./tui/app";
 import { create, type CreateOptions } from "./api";
-import { createProject } from "./helpers/core/create-project";
-import { getDefaultConfig } from "./constants";
 import { getLatestCLIVersion } from "./utils/get-latest-cli-version";
 import { generateReproducibleCommand } from "./utils/generate-reproducible-command";
-import path from "node:path";

27-28: Remove unused type imports.

DirectoryConflict and Template types are imported but never used in this file.

🔎 Proposed fix
 import type {
   PackageManager,
   Database,
   ORM,
   Backend,
   Runtime,
   Frontend,
   Addons,
   Examples,
   DatabaseSetup,
   API,
   WebDeploy,
   ServerDeploy,
-  DirectoryConflict,
-  Template,
   Auth,
   Payments,
   ProjectConfig,
 } from "./types";

143-155: Placeholder add command has defined options but no implementation.

The add command defines several options (--addons, --web-deploy, --server-deploy, --project-dir, --install, --package-manager) but the action only logs a TODO message. Consider either implementing the command or removing the options to avoid confusion.

Would you like me to help implement the add command functionality or create an issue to track this?

.github/workflows/release.yaml (1)

167-183: Consider consistent archive format across platforms.

The script creates .tar.gz for Linux and .zip for Windows/macOS. While this follows platform conventions, the pattern matching *"linux"* could potentially match unexpected directory names. Consider using a more explicit check.

🔎 Proposed improvement for clarity
       - name: Upload binaries to GitHub Release
         if: steps.check-version.outputs.exists == 'false'
         run: |
           VERSION="${{ steps.version.outputs.version }}"
           cd apps/cli/dist
           for dir in better-t-stack-cli-*/; do
             name="${dir%/}"
-            if [[ "$name" == *"linux"* ]]; then
+            if [[ "$name" == *"-linux-"* ]]; then
               tar -czf "${name}.tar.gz" -C "$dir/bin" .
               gh release upload "v$VERSION" "${name}.tar.gz" --clobber
             else
               zip -j "${name}.zip" "$dir/bin/"*
               gh release upload "v$VERSION" "${name}.zip" --clobber
             fi
           done
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
apps/cli/src/tui/app.tsx (1)

576-582: Clarify the keyboard exit behavior.

The condition key.name !== "c" allows exiting on any key except 'c' when in the "done" phase. This seems to prevent accidental exit when trying to use Ctrl+C, but regular 'c' key press also won't exit. Consider checking for the Ctrl modifier instead.

🔎 Proposed improvement
   useKeyboard((key) => {
     if (key.ctrl && key.name === "c") props.onExit();
     // Exit on any key when done
-    if (phase === "done" && key.name !== "c") {
+    if (phase === "done" && !key.ctrl) {
       process.exit(0);
     }
   });
apps/cli/src/index.ts (1)

50-51: Consider using JSDoc @deprecated tag for better tooling support.

Adding a proper JSDoc deprecation annotation will cause IDEs and TypeScript to show deprecation warnings when the init alias is used.

🔎 Proposed improvement
-// Legacy exports for backwards compatibility (deprecated)
-export { create as init } from "./api";
+/**
+ * @deprecated Use `create` instead. This alias will be removed in a future major version.
+ */
+export { create as init } from "./api";
apps/cli/scripts/build.ts (1)

156-161: Variable shadowing: inner pkg shadows outer pkg.

The loop variable pkg at line 158 shadows the outer pkg constant from line 28. This works but can cause confusion. Consider renaming the loop variable.

🔎 Proposed fix
 if (builtPackages.length > 0) {
   console.log("Platform packages:");
-  for (const pkg of builtPackages) {
-    console.log(`  ${pkg.name}@${pkg.version}`);
+  for (const builtPkg of builtPackages) {
+    console.log(`  ${builtPkg.name}@${builtPkg.version}`);
   }
   console.log("\nTo publish, run: bun run scripts/publish.ts");
 }
apps/cli/package.json (1)

68-68: prepublishOnly warning may be insufficient.

The script only echoes a message but doesn't prevent accidental publishing without binaries. Consider either:

  1. Making it fail explicitly: "exit 1"
  2. Or documenting the publish workflow clearly
🔎 Suggested fix to prevent accidental publish
-    "prepublishOnly": "echo 'Build binaries separately before publishing'"
+    "prepublishOnly": "echo 'Error: Build binaries separately before publishing. Run: bun run build' && exit 1"
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d09793 and 6c25d46.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (37)
  • .github/workflows/pr-preview.yaml
  • .github/workflows/release.yaml
  • apps/cli/bin/create-better-t-stack
  • apps/cli/package.json
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/index.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/tsconfig.json
  • apps/cli/tsdown.config.ts
💤 Files with no reviewable changes (1)
  • apps/cli/tsdown.config.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/index.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/index.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/index.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/index.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/tui/app.tsx
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/index.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/tui/app.tsx
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, the Ultracite CLI's `--integrations` flag requires git hooks to be passed as a single space-separated string (e.g., `gitHooks.join(" ")`) rather than using the spread operator like other Ultracite flags. This has been tested and confirmed to work.

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/tsconfig.json
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/bin/create-better-t-stack
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/tsconfig.json
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/scripts/build.ts
  • apps/cli/tsconfig.json
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer `Bun.file` over `node:fs` readFile/writeFile methods

Applied to files:

  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : ONLY call an action from another action if you need to cross runtimes; otherwise, pull out shared code into a helper async function and call that directly

Applied to files:

  • apps/cli/src/helpers/core/convex-codegen.ts
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Always add 'use node'; to the top of files containing actions that use Node.js built-in modules

Applied to files:

  • apps/cli/src/helpers/core/convex-codegen.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` module for SQLite instead of `better-sqlite3`

Applied to files:

  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Applied to files:

  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.sql` for Postgres instead of `pg` or `postgres.js`

Applied to files:

  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/docker-utils.ts
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript type aliases instead of interface declarations

Applied to files:

  • apps/cli/tsconfig.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling

Applied to files:

  • apps/cli/tsconfig.json
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{ts,tsx} : Do not use explicit return types

Applied to files:

  • apps/cli/tsconfig.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.html : HTML files can import .tsx, .jsx or .js files directly; Bun will transpile and bundle automatically

Applied to files:

  • apps/cli/tsconfig.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Run server with `bun --hot <file>` to enable hot reloading during development

Applied to files:

  • apps/cli/tsconfig.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.serve()` which supports WebSockets, HTTPS, and routes instead of `express`

Applied to files:

  • apps/cli/src/constants.ts
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, when passing the Ultracite CLI --integrations flag, supply git hooks as a single space-separated string (e.g., gitHooks.join(" ")) rather than spreading the array like other Ultracite flags. This has been tested and confirmed to work. Ensure the code uses a single string created by joining the gitHooks array with spaces for the --integrations argument.

Applied to files:

  • apps/cli/src/helpers/addons/ultracite-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.redis` for Redis instead of `ioredis`

Applied to files:

  • apps/cli/package.json
🧬 Code graph analysis (6)
apps/cli/src/utils/get-latest-cli-version.ts (1)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (84-84)
apps/cli/src/api.ts (3)
apps/cli/src/constants.ts (1)
  • getDefaultConfig (106-115)
apps/cli/src/helpers/core/create-project.ts (1)
  • createProject (36-134)
apps/cli/src/utils/generate-reproducible-command.ts (1)
  • generateReproducibleCommand (3-53)
apps/cli/test/test-utils.ts (1)
apps/cli/src/api.ts (3)
  • CreateResult (70-85)
  • CreateOptions (31-68)
  • create (108-201)
apps/cli/scripts/publish.ts (1)
apps/cli/scripts/build.ts (2)
  • version (165-165)
  • builtPackages (165-165)
apps/cli/src/helpers/addons/oxlint-setup.ts (1)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/cli.ts (7)
apps/cli/src/utils/get-latest-cli-version.ts (1)
  • getLatestCLIVersion (13-27)
apps/cli/src/tui/app.tsx (1)
  • renderTui (522-539)
apps/cli/src/types.ts (15)
  • Frontend (51-51)
  • Backend (49-49)
  • Runtime (50-50)
  • Database (47-47)
  • ORM (48-48)
  • Auth (57-57)
  • Payments (58-58)
  • Addons (52-52)
  • ProjectConfig (67-67)
  • API (56-56)
  • Examples (53-53)
  • DatabaseSetup (55-55)
  • WebDeploy (59-59)
  • ServerDeploy (60-60)
  • PackageManager (54-54)
apps/cli/src/helpers/core/create-project.ts (1)
  • createProject (36-134)
apps/cli/src/utils/generate-reproducible-command.ts (1)
  • generateReproducibleCommand (3-53)
apps/cli/src/api.ts (1)
  • create (108-201)
apps/cli/src/utils/open-url.ts (1)
  • openUrl (4-18)
🪛 GitHub Actions: Test
apps/cli/src/helpers/core/git.ts

[error] 1-1: Could not resolve: "consola". Maybe you need to "bun install"?

apps/cli/src/helpers/core/install-dependencies.ts

[error] 1-1: Could not resolve: "picocolors". Maybe you need to "bun install"?


[error] 1-1: Could not resolve: "consola". Maybe you need to "bun install"?

apps/cli/src/utils/errors.ts

[error] 1-1: Could not resolve: "consola". Maybe you need to "bun install"?

apps/cli/package.json

[error] 1-1: Dependency resolution failures detected during build; subsequent tests fail due to missing packages.

Comment on lines +72 to +74
"@opentui/core": "^0.1.62",
"@opentui/react": "^0.1.62",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Version mismatch between @opentui/core and platform-specific packages.

The main dependency uses "@opentui/core": "^0.1.62" but the optional platform bindings pin to 0.1.63. This mismatch could cause resolution conflicts or runtime incompatibilities.

🔎 Suggested fix
   "@opentui/core": "^0.1.62",
   "@opentui/react": "^0.1.62",

should align with:

-    "@opentui/core-darwin-arm64": "0.1.63",
-    "@opentui/core-darwin-x64": "0.1.63",
-    "@opentui/core-linux-arm64": "0.1.63",
-    "@opentui/core-linux-x64": "0.1.63",
-    "@opentui/core-win32-arm64": "0.1.63",
-    "@opentui/core-win32-x64": "0.1.63"
+    "@opentui/core-darwin-arm64": "0.1.62",
+    "@opentui/core-darwin-x64": "0.1.62",
+    "@opentui/core-linux-arm64": "0.1.62",
+    "@opentui/core-linux-x64": "0.1.62",
+    "@opentui/core-win32-arm64": "0.1.62",
+    "@opentui/core-win32-x64": "0.1.62"

Or update the main dependency to ^0.1.63.

Also applies to: 98-103

🤖 Prompt for AI Agents
In apps/cli/package.json around lines 72-73 (and also check lines 98-103), the
@opentui/core version (^0.1.62) does not match the platform-specific @opentui
packages pinned to 0.1.63; update the versions so they align. Change either the
main dependency to ^0.1.63 or set the platform bindings to ^0.1.62 consistently
across the file (prefer updating @opentui/core to ^0.1.63) and ensure all
@opentui package entries use the identical version string.

Comment on lines +21 to +24
const dryRun = process.argv.includes("--dry-run");
const tag = process.argv.includes("--tag")
? process.argv[process.argv.indexOf("--tag") + 1]
: "latest";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential undefined value when --tag is the last argument.

If --tag is provided as the last argument without a value, process.argv[indexOf + 1] will be undefined, and the tag will default to "latest" only if --tag is not found. When --tag is present but has no value, tag becomes undefined.

🔎 Proposed fix
 const dryRun = process.argv.includes("--dry-run");
-const tag = process.argv.includes("--tag")
-  ? process.argv[process.argv.indexOf("--tag") + 1]
-  : "latest";
+const tagIndex = process.argv.indexOf("--tag");
+const tag = tagIndex !== -1 && process.argv[tagIndex + 1] && !process.argv[tagIndex + 1].startsWith("--")
+  ? process.argv[tagIndex + 1]
+  : "latest";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const dryRun = process.argv.includes("--dry-run");
const tag = process.argv.includes("--tag")
? process.argv[process.argv.indexOf("--tag") + 1]
: "latest";
const dryRun = process.argv.includes("--dry-run");
const tagIndex = process.argv.indexOf("--tag");
const tag = tagIndex !== -1 && process.argv[tagIndex + 1] && !process.argv[tagIndex + 1].startsWith("--")
? process.argv[tagIndex + 1]
: "latest";
🤖 Prompt for AI Agents
In apps/cli/scripts/publish.ts around lines 21 to 24, when --tag is the last
argument the current logic reads process.argv[index + 1] which may be undefined;
update the logic to check that the index of "--tag" is found and that index + 1
< process.argv.length and the next arg does not start with "--" before using it,
otherwise fall back to "latest" (or optionally error), so tag is never
undefined.

Comment on lines +96 to +103
const optionalDeps: Record<string, string> = {};
for (const built of builtPackages) {
optionalDeps[built.name] = built.version;
}

pkg.optionalDependencies = optionalDeps;
await Bun.write("./package.json", JSON.stringify(pkg, null, 2) + "\n");
console.log(" ✓ Updated package.json\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat apps/cli/package.json | jq '.optionalDependencies // {} | keys | map(select(startswith("@better-t-stack/cli-") | not))'

Repository: AmanVarshney01/create-better-t-stack

Length of output: 264


🏁 Script executed:

cat -n apps/cli/scripts/publish.ts | head -110 | tail -30

Repository: AmanVarshney01/create-better-t-stack

Length of output: 1295


🏁 Script executed:

cat -n apps/cli/package.json | head -50

Repository: AmanVarshney01/create-better-t-stack

Length of output: 1489


🏁 Script executed:

cat -n apps/cli/scripts/publish.ts | head -100 | tail -50

Repository: AmanVarshney01/create-better-t-stack

Length of output: 2107


🏁 Script executed:

grep -n "builtPackages" apps/cli/scripts/publish.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 387


🏁 Script executed:

cat -n apps/cli/scripts/build.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 6458


🏁 Script executed:

cat apps/cli/package.json | jq '.optionalDependencies'

Repository: AmanVarshney01/create-better-t-stack

Length of output: 557


🏁 Script executed:

cat apps/cli/package.json | jq 'keys'

Repository: AmanVarshney01/create-better-t-stack

Length of output: 352


Merge instead of replacing optionalDependencies to preserve @opentui/core- platform packages.*

The code at line 101 uses direct assignment (pkg.optionalDependencies = optionalDeps), which replaces all existing optionalDependencies. However, the current package.json contains 6 @opentui/core-* platform-specific native bindings in addition to the 5 @better-t-stack/cli-* packages being built by this script. Running this script would delete the @opentui/core-* dependencies. Merge the new optionalDeps with the existing optionalDependencies instead of replacing them entirely.

🤖 Prompt for AI Agents
In apps/cli/scripts/publish.ts around lines 96 to 103, the code currently
replaces pkg.optionalDependencies with the newly built optionalDeps which will
remove existing @opentui/core-* entries; instead, merge the new entries into the
existing optionalDependencies so platform packages are preserved. Read
pkg.optionalDependencies (default to {} if undefined), create a merged object
that copies existing entries and then spreads optionalDeps over it so the build
entries overwrite any duplicates, assign that merged object back to
pkg.optionalDependencies, and then write package.json as before.

Comment on lines +134 to +161
frontend:
options.frontend ?? (options.defaults ? defaultConfig.frontend : defaultConfig.frontend),
backend:
options.backend ?? (options.defaults ? defaultConfig.backend : defaultConfig.backend),
runtime:
options.runtime ?? (options.defaults ? defaultConfig.runtime : defaultConfig.runtime),
database:
options.database ?? (options.defaults ? defaultConfig.database : defaultConfig.database),
orm: options.orm ?? (options.defaults ? defaultConfig.orm : defaultConfig.orm),
auth: options.auth ?? (options.defaults ? defaultConfig.auth : defaultConfig.auth),
payments:
options.payments ?? (options.defaults ? defaultConfig.payments : defaultConfig.payments),
api: options.api ?? (options.defaults ? defaultConfig.api : defaultConfig.api),
addons: options.addons ?? (options.defaults ? defaultConfig.addons : defaultConfig.addons),
examples:
options.examples ?? (options.defaults ? defaultConfig.examples : defaultConfig.examples),
dbSetup:
options.dbSetup ?? (options.defaults ? defaultConfig.dbSetup : defaultConfig.dbSetup),
webDeploy:
options.webDeploy ?? (options.defaults ? defaultConfig.webDeploy : defaultConfig.webDeploy),
serverDeploy:
options.serverDeploy ??
(options.defaults ? defaultConfig.serverDeploy : defaultConfig.serverDeploy),
git: options.git ?? (options.defaults ? defaultConfig.git : defaultConfig.git),
packageManager:
options.packageManager ??
(options.defaults ? defaultConfig.packageManager : defaultConfig.packageManager),
install: options.install ?? false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Redundant ternary expressions in config fallback logic.

The ternary expressions options.X ?? (options.defaults ? defaultConfig.X : defaultConfig.X) are redundant since both branches return defaultConfig.X. The options.defaults flag has no effect here.

If the intent is to use interactive prompts when defaults is false, this API bypasses that entirely. If defaults should always be used when a value isn't provided, simplify to options.X ?? defaultConfig.X.

🔎 Proposed fix to simplify the logic
     const config: ProjectConfig = {
       projectName,
       projectDir,
       relativePath,
-      frontend:
-        options.frontend ?? (options.defaults ? defaultConfig.frontend : defaultConfig.frontend),
-      backend:
-        options.backend ?? (options.defaults ? defaultConfig.backend : defaultConfig.backend),
-      runtime:
-        options.runtime ?? (options.defaults ? defaultConfig.runtime : defaultConfig.runtime),
-      database:
-        options.database ?? (options.defaults ? defaultConfig.database : defaultConfig.database),
-      orm: options.orm ?? (options.defaults ? defaultConfig.orm : defaultConfig.orm),
-      auth: options.auth ?? (options.defaults ? defaultConfig.auth : defaultConfig.auth),
-      payments:
-        options.payments ?? (options.defaults ? defaultConfig.payments : defaultConfig.payments),
-      api: options.api ?? (options.defaults ? defaultConfig.api : defaultConfig.api),
-      addons: options.addons ?? (options.defaults ? defaultConfig.addons : defaultConfig.addons),
-      examples:
-        options.examples ?? (options.defaults ? defaultConfig.examples : defaultConfig.examples),
-      dbSetup:
-        options.dbSetup ?? (options.defaults ? defaultConfig.dbSetup : defaultConfig.dbSetup),
-      webDeploy:
-        options.webDeploy ?? (options.defaults ? defaultConfig.webDeploy : defaultConfig.webDeploy),
-      serverDeploy:
-        options.serverDeploy ??
-        (options.defaults ? defaultConfig.serverDeploy : defaultConfig.serverDeploy),
-      git: options.git ?? (options.defaults ? defaultConfig.git : defaultConfig.git),
-      packageManager:
-        options.packageManager ??
-        (options.defaults ? defaultConfig.packageManager : defaultConfig.packageManager),
+      frontend: options.frontend ?? defaultConfig.frontend,
+      backend: options.backend ?? defaultConfig.backend,
+      runtime: options.runtime ?? defaultConfig.runtime,
+      database: options.database ?? defaultConfig.database,
+      orm: options.orm ?? defaultConfig.orm,
+      auth: options.auth ?? defaultConfig.auth,
+      payments: options.payments ?? defaultConfig.payments,
+      api: options.api ?? defaultConfig.api,
+      addons: options.addons ?? defaultConfig.addons,
+      examples: options.examples ?? defaultConfig.examples,
+      dbSetup: options.dbSetup ?? defaultConfig.dbSetup,
+      webDeploy: options.webDeploy ?? defaultConfig.webDeploy,
+      serverDeploy: options.serverDeploy ?? defaultConfig.serverDeploy,
+      git: options.git ?? defaultConfig.git,
+      packageManager: options.packageManager ?? defaultConfig.packageManager,
       install: options.install ?? false,
     };
🤖 Prompt for AI Agents
In apps/cli/src/api.ts around lines 134 to 161, the fallback expressions use
redundant ternaries like options.X ?? (options.defaults ? defaultConfig.X :
defaultConfig.X); replace each with the simpler options.X ?? defaultConfig.X so
the defaults flag no longer has no-op branches; if interactive prompting when
options.defaults is false is required, implement that branching separately
(e.g., call the prompt logic when options.X is undefined and options.defaults
=== false) rather than keeping identical ternary arms.

Comment on lines 48 to 56
await $`brew install tursodatabase/tap/turso`;
} else {
const { stdout: installScript } = await $`curl -sSfL https://get.tur.so/install.sh`;
await $`bash -c '${installScript}'`;
const installScript = await $`curl -sSfL https://get.tur.so/install.sh`.text();
await $`bash -c ${installScript}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical security issue: Executing downloaded script without verification.

The code downloads an installation script from the internet and executes it with bash without any verification. This is a serious security vulnerability that could allow arbitrary code execution if the download is compromised or redirected.

🔎 Recommended security improvements

Consider one of these approaches:

  1. Verify the script with a checksum:
const installScript = await $`curl -sSfL https://get.tur.so/install.sh`.text();
const expectedHash = "EXPECTED_SHA256_HASH"; // Update with actual hash
const actualHash = await $`echo ${installScript} | sha256sum`.text();
if (!actualHash.includes(expectedHash)) {
  throw new Error("Installation script verification failed");
}
await $`bash -c ${installScript}`;
  1. Prompt the user for confirmation:
log.warn("About to download and execute installation script from https://get.tur.so/install.sh");
const shouldProceed = await confirm({
  message: "Do you want to proceed with the installation?",
  initialValue: false,
});
if (!shouldProceed) {
  throw new Error("Installation cancelled");
}
const installScript = await $`curl -sSfL https://get.tur.so/install.sh`.text();
await $`bash -c ${installScript}`;
  1. Use a more secure installation method or direct the user to manual installation.
🤖 Prompt for AI Agents
In apps/cli/src/helpers/database-providers/turso-setup.ts around lines 48–52,
the code downloads an installation script and directly executes it with bash,
which is a critical arbitrary-code execution risk; fix by not piping unverified
remote content directly to bash — instead download the script to a temporary
file, compute and compare its SHA-256 (or other strong) checksum against a
known, trusted value fetched from a secure source (or hardcoded if appropriate),
and only execute the file after the checksum matches; as an alternative or
additional protection, prompt the user for explicit confirmation before
executing, or skip automatic execution entirely and instruct the user to run the
verified script manually; ensure any execution uses the verified temp file (not
bash -c with untrusted string) and handle mismatches by aborting with a clear
error.

Comment on lines 637 to 783
const cfg: ProjectConfig = {
...defaultConfig,
...config,
projectName: config.projectName ?? "my-app",
projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
relativePath: config.projectName ?? "my-app",
frontend: config.frontend?.length ? config.frontend : ["tanstack-router"],
addons: config.addons?.length ? config.addons : ["none"],
examples: config.examples ?? [],
git: config.git === true,
install: config.install === true,
} as ProjectConfig;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use path.join instead of string concatenation for paths.

String concatenation with / won't work correctly on Windows. Use path.join for cross-platform compatibility.

🔎 Proposed fix
+import path from "node:path";
+
 // In handleComplete:
 const cfg: ProjectConfig = {
   ...defaultConfig,
   ...config,
   projectName: config.projectName ?? "my-app",
-  projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
+  projectDir: path.join(process.cwd(), config.projectName ?? "my-app"),
   relativePath: config.projectName ?? "my-app",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cfg: ProjectConfig = {
...defaultConfig,
...config,
projectName: config.projectName ?? "my-app",
projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
relativePath: config.projectName ?? "my-app",
frontend: config.frontend?.length ? config.frontend : ["tanstack-router"],
addons: config.addons?.length ? config.addons : ["none"],
examples: config.examples ?? [],
git: config.git === true,
install: config.install === true,
} as ProjectConfig;
import path from "node:path";
const cfg: ProjectConfig = {
...defaultConfig,
...config,
projectName: config.projectName ?? "my-app",
projectDir: path.join(process.cwd(), config.projectName ?? "my-app"),
relativePath: config.projectName ?? "my-app",
frontend: config.frontend?.length ? config.frontend : ["tanstack-router"],
addons: config.addons?.length ? config.addons : ["none"],
examples: config.examples ?? [],
git: config.git === true,
install: config.install === true,
} as ProjectConfig;
🤖 Prompt for AI Agents
In apps/cli/src/tui/app.tsx around lines 637 to 648, the code builds projectDir
by concatenating process.cwd() + "/" + projectName which breaks on Windows;
import Node's path module (import path from "path" or require("path")) and
replace the string concatenation with path.join(process.cwd(), projectNameValue)
where projectNameValue is the resolved project name (e.g., const projectName =
config.projectName ?? "my-app"); keep relativePath as the projectName string and
ensure projectDir is computed via path.join to ensure cross-platform
compatibility.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c25d46 and 04fb0e7.

📒 Files selected for processing (1)
  • .github/workflows/pr-preview.yaml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Comment on lines +104 to +117
- name: Publish CLI platform packages to NPM
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public --tag ${{ steps.version.outputs.tag }}
cd ..
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Working directory not restored, breaking subsequent steps.

After this step completes, the working directory remains apps/cli/dist instead of the repository root. This will cause the next two publish steps (lines 120 and 125) to fail because they use relative paths (cd apps/cli and cd packages/create-bts) that expect to be run from the root directory.

🔎 Proposed fix
      - name: Publish CLI platform packages to NPM
        run: |
          cd apps/cli/dist
          ls -la
          for dir in */; do
            if [ -f "$dir/package.json" ]; then
              echo "Publishing $dir..."
              cd "$dir"
              bun publish --access public --tag ${{ steps.version.outputs.tag }}
              cd ..
            fi
          done
+         cd ../../..
        env:
          NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

Alternatively, use a subshell to avoid changing the working directory of the step:

      - name: Publish CLI platform packages to NPM
        run: |
-         cd apps/cli/dist
-         ls -la
-         for dir in */; do
-           if [ -f "$dir/package.json" ]; then
-             echo "Publishing $dir..."
-             cd "$dir"
-             bun publish --access public --tag ${{ steps.version.outputs.tag }}
-             cd ..
-           fi
-         done
+         (
+           cd apps/cli/dist
+           ls -la
+           for dir in */; do
+             if [ -f "$dir/package.json" ]; then
+               echo "Publishing $dir..."
+               cd "$dir"
+               bun publish --access public --tag ${{ steps.version.outputs.tag }}
+               cd ..
+             fi
+           done
+         )
        env:
          NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Publish CLI platform packages to NPM
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public --tag ${{ steps.version.outputs.tag }}
cd ..
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish CLI platform packages to NPM
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public --tag ${{ steps.version.outputs.tag }}
cd ..
fi
done
cd ../../..
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
🤖 Prompt for AI Agents
.github/workflows/pr-preview.yaml around lines 104 to 117: the step changes the
working directory to apps/cli/dist and does not restore it, so subsequent steps
using relative paths fail; to fix, run the publish loop in a subshell or
explicitly restore the original directory (e.g., wrap the cd and loop in
parentheses or use pushd/popd and popd at the end) so the workflow's working
directory remains the repository root before the next steps run.

⚠️ Potential issue | 🟠 Major

Add error handling to fail on first publish error.

The loop continues even if a platform package fails to publish. Without explicit error handling, the step might succeed despite some platforms failing to publish, leading to incomplete preview releases.

🔎 Proposed fix

Add set -e at the beginning of the script to fail immediately on any error:

      - name: Publish CLI platform packages to NPM
        run: |
+         set -e
          cd apps/cli/dist
          ls -la
          for dir in */; do
            if [ -f "$dir/package.json" ]; then
              echo "Publishing $dir..."
              cd "$dir"
              bun publish --access public --tag ${{ steps.version.outputs.tag }}
              cd ..
            fi
          done
        env:
          NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
🤖 Prompt for AI Agents
.github/workflows/pr-preview.yaml around lines 104 to 117: the publish loop
continues on errors so a failed bun publish can be silently ignored; modify the
shell script to fail fast by enabling errexit (e.g., add `set -e` or `set -o
errexit` at the start of the run block) so the step exits immediately on any
publish error (alternatively ensure each publish command is checked and exits
non‑zero on failure).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
.github/workflows/pr-preview-push.yaml (3)

43-59: Consider validating the generated preview version format.

The version generation logic truncates branch names to 20 characters and assumes a clean X.Y.Z base version. This could produce confusing versions for long branch names or fail if package.json already contains a pre-release version.

Consider adding validation:

  • Check that the generated version is valid semver
  • Warn if branch name was truncated
  • Handle existing pre-release versions in BASE_VERSION

Example validation:

# After line 50, add:
if ! echo "$PREVIEW_VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+-[0-9A-Za-z.-]+$'; then
  echo "Error: Generated version '$PREVIEW_VERSION' is not valid semver"
  exit 1
fi

60-72: Add error handling for package build and publish steps.

The types package workflow lacks error handling. If the build or publish fails, subsequent steps will continue with outdated or missing packages, leading to inconsistent preview releases.

🔎 Proposed fix

Add set -e to fail fast on errors:

       - name: Update types package version
         run: |
+          set -e
           cd packages/types
           jq --arg v "${{ steps.version.outputs.version }}" '.version = $v' package.json > tmp.json && mv tmp.json package.json
 
       - name: Build types package
-        run: cd packages/types && bun run build
+        run: |
+          set -e
+          cd packages/types && bun run build
 
       - name: Publish types to NPM
-        run: cd packages/types && bun publish --access public --tag ${{ steps.version.outputs.tag }}
+        run: |
+          set -e
+          cd packages/types && bun publish --access public --tag ${{ steps.version.outputs.tag }}
         env:
           NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

92-96: Add verification that platform packages were created.

After building the CLI binaries, verify that the expected platform packages exist under apps/cli/dist before attempting to publish them. This prevents silent failures if the build doesn't produce the expected structure.

🔎 Proposed fix

Add a verification step after the build:

      - name: Build CLI binaries
        run: cd apps/cli && bun run build
        env:
          BTS_TELEMETRY: 0

      - name: Verify build output
        run: |
          set -e
          cd apps/cli/dist
          EXPECTED_PACKAGES=("cli-darwin-arm64" "cli-darwin-x64" "cli-linux-arm64" "cli-linux-x64" "cli-windows-x64")
          for pkg in "${EXPECTED_PACKAGES[@]}"; do
            if [ ! -d "$pkg" ] || [ ! -f "$pkg/package.json" ]; then
              echo "Error: Expected platform package $pkg not found or invalid"
              exit 1
            fi
          done
          echo "All platform packages verified"
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04fb0e7 and 37fc326.

📒 Files selected for processing (1)
  • .github/workflows/pr-preview-push.yaml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
🔇 Additional comments (3)
.github/workflows/pr-preview-push.yaml (3)

73-91: The version synchronization logic looks correct.

The package version and dependency updates correctly synchronize all platform-specific optional dependencies and the types dependency to the preview version.


122-131: The summary generation looks good.

The summary provides clear installation instructions for the preview version using the generated version tag.


68-72: No action needed. NPM authentication is correctly configured.

bun publish supports NPM_CONFIG_TOKEN and this is the recommended pattern for GitHub Actions, as documented in the official bun CLI reference. The workflow is using the correct approach.

Comment on lines +3 to +10
on:
push:
branches:
- "**"
paths:
- "apps/cli/**"
- "packages/types/**"
- ".github/workflows/pr-preview-push.yaml"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Add fork protection to prevent secret exposure.

This workflow triggers on pushes from any branch, including forks. Fork contributors would gain access to NPM_TOKEN, creating a severe security risk. Add a condition to prevent execution on forks.

🔎 Proposed fix
 on:
   push:
     branches:
       - "**"
     paths:
       - "apps/cli/**"
       - "packages/types/**"
       - ".github/workflows/pr-preview-push.yaml"

Then add a fork check to the job condition:

   publish-preview:
     name: Publish Preview
     runs-on: ubuntu-latest
-    if: github.ref != 'refs/heads/main'
+    if: github.ref != 'refs/heads/main' && github.event.repository.fork == false
     timeout-minutes: 30

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
.github/workflows/pr-preview-push.yaml around lines 3 to 10: the workflow
currently triggers on pushes from any branch/paths and can run for events
originating from forked repos, risking exposure of secrets like NPM_TOKEN; add a
job-level condition that prevents execution for events originating from forks
(e.g., only run when the event repository matches the base repository or when
the pull_request head repo equals the base repo), by adding an if check to the
workflow jobs so the pipeline only runs for non-forked events.

Comment on lines +12 to +15
permissions:
contents: read
pull-requests: write
id-token: write
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove unused permissions following least-privilege principle.

The id-token: write and pull-requests: write permissions are not used in this workflow. The workflow writes to GITHUB_STEP_SUMMARY (a workflow-level summary), not PR comments, and doesn't use OIDC authentication.

🔎 Proposed fix
 permissions:
   contents: read
-  pull-requests: write
-  id-token: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
permissions:
contents: read
pull-requests: write
id-token: write
permissions:
contents: read
🤖 Prompt for AI Agents
.github/workflows/pr-preview-push.yaml around lines 12 to 15: the workflow
currently grants unnecessary permissions; remove the unused id-token: write and
pull-requests: write entries and keep only the minimal permissions required
(e.g., contents: read) so the workflow follows the least-privilege principle.

Comment on lines +97 to +111
- name: Publish CLI platform packages to NPM
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public --tag ${{ steps.version.outputs.tag }}
cd ..
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add error handling in the platform package publishing loop.

The loop publishes each platform package but doesn't handle failures. If one package fails to publish, the workflow continues, resulting in an incomplete preview release.

🔎 Proposed fix
       - name: Publish CLI platform packages to NPM
         run: |
+          set -e
           cd apps/cli/dist
           ls -la
           for dir in */; do
             if [ -f "$dir/package.json" ]; then
               echo "Publishing $dir..."
-              cd "$dir"
+              cd "$dir" || exit 1
               bun publish --access public --tag ${{ steps.version.outputs.tag }}
-              cd ..
+              PUBLISH_EXIT=$?
+              cd .. || exit 1
+              if [ $PUBLISH_EXIT -ne 0 ]; then
+                echo "Failed to publish $dir"
+                exit 1
+              fi
+              echo "Successfully published $dir"
             fi
           done
         env:
           NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Publish CLI platform packages to NPM
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public --tag ${{ steps.version.outputs.tag }}
cd ..
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish CLI platform packages to NPM
run: |
set -e
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir" || exit 1
bun publish --access public --tag ${{ steps.version.outputs.tag }}
PUBLISH_EXIT=$?
cd .. || exit 1
if [ $PUBLISH_EXIT -ne 0 ]; then
echo "Failed to publish $dir"
exit 1
fi
echo "Successfully published $dir"
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
🤖 Prompt for AI Agents
In .github/workflows/pr-preview-push.yaml around lines 97 to 111, the publish
loop runs bun publish for each platform package but does not handle failures, so
a single failing publish can be silently ignored and produce an incomplete
preview release; update the script to detect publish failures and fail the job
(or collect and report failures) by checking bun publish's exit code after each
publish, echoing a clear error with package name and exit status, and exiting
with a non-zero status if any publish fails (alternatively accumulate failed
package names and exit non-zero after the loop with a summary).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/cli/src/helpers/addons/addons-setup.ts (1)

34-42: Add picocolors to the dependency version map.

The import of picocolors at line 3 is not declared in apps/cli/src/constants.ts under dependencyVersionMap, even though it's used throughout the CLI codebase. This is a missing dependency that must be added to the version map following the project's dependency management pattern, rather than a build configuration issue.

♻️ Duplicate comments (2)
apps/cli/src/tui/app.tsx (2)

524-541: The Promise returned by renderTui never resolves.

This issue was flagged in a previous review and remains unresolved. The Promise only exits via process.exit(0) calls, so any code awaiting this function will never continue execution normally. Consider either:

  1. Resolving/rejecting the Promise in onCancel and onComplete handlers instead of calling process.exit
  2. Changing the return type to void and documenting that this function terminates the process

671-696: Use path.join for cross-platform path construction.

This issue was flagged in a previous review. Line 677 uses string concatenation with / which won't work correctly on Windows. Import Node's path module and use path.join(process.cwd(), config.projectName ?? "my-app") for cross-platform compatibility.

🔎 Proposed fix

Add the import at the top of the file:

+import path from "node:path";

Then update line 677:

-  projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
+  projectDir: path.join(process.cwd(), config.projectName ?? "my-app"),
🧹 Nitpick comments (5)
apps/cli/src/helpers/core/git.ts (1)

21-21: Simplify commit message template literal.

The string interpolation ${"initial commit"} is unnecessary. You can use the string directly in the template literal.

🔎 Proposed simplification
- await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
+ await $`git commit -m "initial commit"`.cwd(projectDir).quiet();
apps/cli/src/helpers/addons/oxlint-setup.ts (1)

27-35: Consider adding error handling for consistency.

Unlike starlight-setup.ts and tauri-setup.ts which wrap Bun $ commands in try/catch and call log.error on failure, this function lacks error handling. If oxlint --init or oxfmt --init fails, the error will propagate uncaught.

🔎 Proposed fix
+  try {
     log.step("Initializing oxlint and oxfmt...");

     const oxlintInitCommand = getPackageExecutionCommand(packageManager, "oxlint@latest --init");
     await $`${{ raw: oxlintInitCommand }}`.cwd(projectDir).env({ CI: "true" });

     const oxfmtInitCommand = getPackageExecutionCommand(packageManager, "oxfmt@latest --init");
     await $`${{ raw: oxfmtInitCommand }}`.cwd(projectDir).env({ CI: "true" });

     log.success("oxlint and oxfmt initialized successfully!");
+  } catch (error) {
+    log.error("Failed to initialize oxlint and oxfmt");
+    if (error instanceof Error) {
+      console.error(error.message);
+    }
+  }
apps/cli/src/helpers/addons/starlight-setup.ts (1)

38-42: Consider consolidating error logging.

The error handling uses both log.error (line 39) and consola.error (line 41). If the internal logger is meant to be the unified logging solution, consider using only the internal logger, or ensure there's a clear purpose for dual-channel error output.

apps/cli/src/tui/use-logger.ts (2)

8-24: Consider using standard function declarations.

Per coding guidelines, prefer standard function declaration syntax over arrow functions for defining functions. The hooks are correctly implemented with proper cleanup.

🔎 Already using standard function declarations

Looking more closely, useLogger and useLatestLog are already defined with the function keyword, so this is compliant. The implementation is correct.

LGTM!

The hooks properly:

  • Initialize state from existing logs
  • Subscribe to new log entries
  • Clean up subscriptions on unmount

The React patterns are correctly applied.

Also applies to: 27-44


9-9: Minor: Consider using lazy initialization.

For useState with computed initial values, lazy initialization avoids calling logger.getLogs() on every render:

-const [logs, setLogs] = useState<LogEntry[]>([]);
+const [logs, setLogs] = useState<LogEntry[]>(() => logger.getLogs());

This would also remove the need for setLogs(logger.getLogs()) inside the effect.

Also applies to: 28-28

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37fc326 and 9db6a48.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/prompts/api.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/prompts/backend.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/src/prompts/database-setup.ts
  • apps/cli/src/prompts/database.ts
  • apps/cli/src/prompts/examples.ts
  • apps/cli/src/prompts/frontend.ts
  • apps/cli/src/prompts/git.ts
  • apps/cli/src/prompts/install.ts
  • apps/cli/src/prompts/orm.ts
  • apps/cli/src/prompts/package-manager.ts
  • apps/cli/src/prompts/payments.ts
  • apps/cli/src/prompts/project-name.ts
  • apps/cli/src/prompts/runtime.ts
  • apps/cli/src/prompts/server-deploy.ts
  • apps/cli/src/prompts/web-deploy.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/utils/open-url.ts
  • opentui
💤 Files with no reviewable changes (18)
  • apps/cli/src/prompts/install.ts
  • apps/cli/src/prompts/database.ts
  • apps/cli/src/prompts/package-manager.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/prompts/git.ts
  • apps/cli/src/prompts/database-setup.ts
  • apps/cli/src/prompts/runtime.ts
  • apps/cli/src/prompts/backend.ts
  • apps/cli/src/prompts/examples.ts
  • apps/cli/src/prompts/orm.ts
  • apps/cli/src/prompts/api.ts
  • apps/cli/src/prompts/payments.ts
  • apps/cli/src/prompts/project-name.ts
  • apps/cli/src/prompts/frontend.ts
  • apps/cli/src/prompts/server-deploy.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/prompts/web-deploy.ts
✅ Files skipped from review due to trivial changes (1)
  • opentui
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, the Ultracite CLI's `--integrations` flag requires git hooks to be passed as a single space-separated string (e.g., `gitHooks.join(" ")`) rather than using the spread operator like other Ultracite flags. This has been tested and confirmed to work.

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer `Bun.file` over `node:fs` readFile/writeFile methods

Applied to files:

  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Always add 'use node'; to the top of files containing actions that use Node.js built-in modules

Applied to files:

  • apps/cli/src/tui/app.tsx
🧬 Code graph analysis (4)
apps/cli/src/tui/use-logger.ts (1)
apps/cli/src/utils/logger.ts (2)
  • LogEntry (8-13)
  • logger (71-71)
apps/cli/src/helpers/addons/tauri-setup.ts (1)
apps/cli/src/utils/logger.ts (2)
  • log (74-80)
  • error (52-54)
apps/cli/src/helpers/addons/oxlint-setup.ts (2)
apps/cli/src/utils/logger.ts (1)
  • log (74-80)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/tui/app.tsx (4)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/tui/use-logger.ts (1)
  • useLogger (8-24)
apps/cli/src/utils/logger.ts (4)
  • LogEntry (8-13)
  • log (74-80)
  • step (56-58)
  • error (52-54)
apps/cli/src/constants.ts (1)
  • getDefaultConfig (106-115)
🪛 GitHub Actions: Test
apps/cli/src/helpers/core/git.ts

[error] 2-2: Build failed: Could not resolve module 'picocolors'. Dependency may not be installed. Run 'bun install' to install missing dependencies.

apps/cli/src/helpers/addons/addons-setup.ts

[error] 3-3: Build failed: Could not resolve module 'picocolors'. Dependency may not be installed. Run 'bun install' to install missing dependencies.

🔇 Additional comments (19)
apps/cli/src/helpers/core/project-config.ts (2)

2-2: LGTM! Import aligns with Bun migration.

The addition of $ from "bun" correctly supports the migration from execa to Bun's command execution API.

Based on learnings, Bun.$ template literal syntax should be used instead of execa for shell command execution.


94-99: LGTM! Bun.$ migration correctly implemented.

The migration from execa to Bun's $ command execution is correct:

  • .cwd(projectDir) properly sets the working directory
  • .text() captures stdout as a string
  • Error handling is preserved
  • The logging change to console.warn is appropriate given the removal of the log utility

Based on learnings, Bun.$ template literal syntax should be used instead of execa for shell command execution.

apps/cli/src/helpers/core/git.ts (2)

7-12: LGTM! Git availability check is correctly implemented.

The migration to Bun's $ template literal syntax is correct. The use of .nothrow().quiet() properly handles the case where Git is not installed, and the early return prevents subsequent operations from failing.

Based on learnings, this correctly uses Bun.$ template literal syntax instead of execa.


14-18: No changes needed — stderr access pattern is correct.

The result.stderr.toString() pattern is correct for Bun's $ API. The shell command returns { stderr } as a Buffer by default, and calling .toString() is the proper way to convert it to a string for the error message.

apps/cli/src/helpers/core/add-deployment.ts (1)

69-71: LGTM!

The logging changes from log.info to console.log with styled ℹ prefixes are consistent with the PR's migration pattern. The functional behavior remains unchanged.

Also applies to: 75-75, 93-95

apps/cli/src/helpers/core/add-addons.ts (1)

76-78: LGTM!

Consistent with the logging migration pattern used across other helper files in this PR.

apps/cli/src/helpers/addons/oxlint-setup.ts (1)

2-7: Good migration to Bun's $ template literal syntax.

The import changes correctly follow the coding guidelines for using Bun.$ instead of execa for shell command execution. Based on learnings.

apps/cli/src/helpers/addons/starlight-setup.ts (1)

3-3: Good migration to Bun's $ for shell execution.

The switch from execa to Bun's $ template literal aligns with the coding guidelines. The raw command form and .cwd()/.env() chaining correctly preserve the working directory and environment settings. Based on learnings.

Also applies to: 35-35

apps/cli/src/helpers/addons/tauri-setup.ts (1)

3-3: Good migration to Bun's $ template literal.

Correctly follows the coding guidelines for shell command execution using Bun.$ instead of execa. The error handling pattern is consistent with starlight-setup.ts. Based on learnings.

Also applies to: 9-9, 80-80

apps/cli/src/helpers/core/create-project.ts (1)

3-3: LGTM!

Clean migration from @clack/prompts log to the internal logger utility. This centralizes logging through the project's own logger infrastructure, enabling TUI integration.

apps/cli/src/utils/logger.ts (2)

1-68: LGTM! Well-designed logging system.

The Logger class uses a clean observer pattern with a Set-based listener registry, proper encapsulation of private state, and returns an unsubscribe function from subscribe for easy cleanup. The copy in getLogs() prevents external mutations.


70-80: LGTM! Clean convenience API.

The global singleton pattern is appropriate for logging, and the convenience wrapper provides an ergonomic API for consumers.

apps/cli/src/tui/app.tsx (7)

1-46: LGTM! Clean imports and type definitions.

The TuiOptions interface provides a clear public API surface, and the theme configuration is well-structured for the terminal UI.


48-522: LGTM! Comprehensive step configuration.

The STEPS array provides a well-structured declarative configuration for the multi-step questionnaire with conditional visibility and dynamic options that match the existing prompt system.


543-595: LGTM! Well-implemented UI components.

The Spinner component properly manages its interval lifecycle with cleanup, and the LogDisplay component effectively maps log levels to visual indicators while limiting display to the most recent 15 entries.


633-669: LGTM! Robust navigation logic.

The navigation implementation correctly handles conditional step visibility, applies defaults for skipped steps, and provides bidirectional navigation through visible steps only.


738-825: LGTM! Well-structured phase rendering.

The prompts phase rendering effectively shows completed, current, and future steps with appropriate visual indicators and delegates to the correct input components based on step type.


827-915: LGTM! Clear and informative phase transitions.

The creating and done phases provide excellent user feedback with real-time logs during creation and clear, conditional next steps upon completion.


940-1101: LGTM! Consistent and accessible input components.

All prompt components follow a consistent pattern with proper keyboard handling, clear visual feedback, and support for bidirectional navigation. The keyboard shortcuts are intuitive and well-documented in the UI.

Comment on lines +20 to +21
await $`git add -A`.cwd(projectDir).quiet();
await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for git add and commit operations.

These commands use .quiet() but not .nothrow(), which means they will throw unhandled errors if they fail. This is inconsistent with the explicit error handling pattern used for git init above. Consider adding .nothrow() and checking exit codes, or wrapping these in try-catch to provide better error messages.

🔎 Suggested fix with consistent error handling
- await $`git add -A`.cwd(projectDir).quiet();
- await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
+ const addResult = await $`git add -A`.cwd(projectDir).nothrow().quiet();
+ if (addResult.exitCode !== 0) {
+   throw new Error(`Git add failed: ${addResult.stderr.toString()}`);
+ }
+ 
+ const commitResult = await $`git commit -m "initial commit"`.cwd(projectDir).nothrow().quiet();
+ if (commitResult.exitCode !== 0) {
+   throw new Error(`Git commit failed: ${commitResult.stderr.toString()}`);
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await $`git add -A`.cwd(projectDir).quiet();
await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
const addResult = await $`git add -A`.cwd(projectDir).nothrow().quiet();
if (addResult.exitCode !== 0) {
throw new Error(`Git add failed: ${addResult.stderr.toString()}`);
}
const commitResult = await $`git commit -m "initial commit"`.cwd(projectDir).nothrow().quiet();
if (commitResult.exitCode !== 0) {
throw new Error(`Git commit failed: ${commitResult.stderr.toString()}`);
}
🤖 Prompt for AI Agents
In apps/cli/src/helpers/core/git.ts around lines 20-21, the git add and git
commit calls use .quiet() but not .nothrow(), so failures will throw unhandled
errors and are inconsistent with the git init error handling; update these calls
to either append .nothrow() and inspect the returned exit code/result to log or
throw a descriptive error on failure, or wrap each await in try/catch and emit a
clear error message (including command, projectDir and underlying error/exit
code) before rethrowing or returning a failure result to match the pattern used
for git init.

Comment on lines +759 to +264
{currentStep.type === "input" && (
<InputPrompt
onSubmit={(v) => {
updateConfig(currentStep.id, v);
if (currentStep.id === "projectName") {
updateConfig("projectDir", process.cwd() + "/" + v);
updateConfig("relativePath", v);
}
goNext();
}}
onBack={stepIndex > 0 ? goPrev : undefined}
/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use path.join for projectDir path construction.

Line 764 also uses string concatenation with / for path construction. This should be updated along with line 677 to use path.join for cross-platform compatibility.

🔎 Proposed fix
                  <InputPrompt
                    onSubmit={(v) => {
                      updateConfig(currentStep.id, v);
                      if (currentStep.id === "projectName") {
-                       updateConfig("projectDir", process.cwd() + "/" + v);
+                       updateConfig("projectDir", path.join(process.cwd(), v));
                        updateConfig("relativePath", v);
                      }
                      goNext();
                    }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{currentStep.type === "input" && (
<InputPrompt
onSubmit={(v) => {
updateConfig(currentStep.id, v);
if (currentStep.id === "projectName") {
updateConfig("projectDir", process.cwd() + "/" + v);
updateConfig("relativePath", v);
}
goNext();
}}
onBack={stepIndex > 0 ? goPrev : undefined}
/>
{currentStep.type === "input" && (
<InputPrompt
onSubmit={(v) => {
updateConfig(currentStep.id, v);
if (currentStep.id === "projectName") {
updateConfig("projectDir", path.join(process.cwd(), v));
updateConfig("relativePath", v);
}
goNext();
}}
onBack={stepIndex > 0 ? goPrev : undefined}
/>
🤖 Prompt for AI Agents
In apps/cli/src/tui/app.tsx around lines 759 to 770 (and also update the earlier
occurrence at line ~677), the code builds projectDir using string concatenation
with "/" which is not cross-platform; replace those concatenations with
path.join(process.cwd(), v) (and similarly for the other spot) and ensure the
file imports Node's path module (e.g., add a top-level import if missing).
Update the InputPrompt onSubmit to call updateConfig("projectDir",
path.join(process.cwd(), v)) and update any other concatenations in the file to
use path.join for correct Windows compatibility.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
apps/cli/package.json (1)

73-74: Version mismatch between @opentui/core and platform-specific packages.

The core @opentui/core dependency is pinned to ^0.1.62, but the platform-specific native bindings in optionalDependencies (lines 101-106) are pinned to 0.1.63. This mismatch can cause resolution conflicts or runtime incompatibilities when the platform package expects APIs from version 0.1.63 but the core is on 0.1.62.

🔎 Recommended fix

Align versions by updating the core dependency to match:

- "@opentui/core": "^0.1.62",
- "@opentui/react": "^0.1.62",
+ "@opentui/core": "^0.1.63",
+ "@opentui/react": "^0.1.63",

This ensures the platform-specific native bindings are compatible with the core package.

Also applies to: 101-106

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9db6a48 and a1fcb7b.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • apps/cli/package.json
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` module for SQLite instead of `better-sqlite3`

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Run server with `bun --hot <file>` to enable hot reloading during development

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.redis` for Redis instead of `ioredis`

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to package.json : Always add types/node to your package.json when using any Node.js built-in modules

Applied to files:

  • apps/cli/package.json
🔇 Additional comments (1)
apps/cli/package.json (1)

81-81: Update React to version 19.2.3.

The package specifies react@^19.1.0, but the latest stable version is 19.2.3 (released Dec 11, 2025). Update to ^19.2.3 to include the latest bug fixes and improvements within React 19. While the caret allows npm to install 19.2.3, explicitly specifying it ensures consistency across environments.

Note: Since this is a CLI tool that bundles dependencies (not a library consumed by others), React as a regular dependency is appropriate.

Comment on lines 42 to 54
"files": [
"dist",
"bin",
"src",
"templates"
],
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs"
},
"./cli": {
"import": "./dist/cli.mjs"
"types": "./src/index.ts",
"import": "./src/index.ts"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Publishing TypeScript source files will break package consumers.

The package configuration now publishes the src directory and points main, types, and exports to TypeScript source files (./src/index.ts). This configuration will fail for published packages because:

  1. Node.js cannot execute .ts files directly
  2. Most consumers expect pre-compiled JavaScript with separate .d.ts type definitions
  3. TypeScript source requires exact compiler configuration match

This likely works locally during development but will break when published to npm.

🔎 Expected configuration for published packages

The build process should output compiled files, and the package.json should reference them:

  "files": [
    "bin",
-   "src",
+   "dist",
    "templates"
  ],
  "type": "module",
- "main": "./src/index.ts",
- "types": "./src/index.ts",
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
  "exports": {
    ".": {
-     "types": "./src/index.ts",
-     "import": "./src/index.ts"
+     "types": "./dist/index.d.ts",
+     "import": "./dist/index.js"
    }
  }

Alternatively, if this is intentional for a Bun-only package that compiles platform-specific binaries separately, document this clearly and ensure the prepublishOnly script validates that binaries are present.

🤖 Prompt for AI Agents
In apps/cli/package.json around lines 42 to 54, the package currently publishes
the TypeScript source and points main/types/exports to ./src/index.ts which will
break consumers; update package.json to publish compiled output (e.g., change
"files" to include "dist" instead of "src"), point "main" to the compiled JS
(e.g., "./dist/index.js"), "types" to the generated declaration file (e.g.,
"./dist/index.d.ts"), and adjust "exports" to reference the dist paths; also
ensure there is a build script that emits JS and .d.ts and add a prepublishOnly
(or prepare) script that runs the build so published packages contain only
compiled code.

"test:watch": "bun test --watch",
"test:coverage": "bun test --coverage",
"test:ci": "AGENT=1 bun test --bail=5",
"prepublishOnly": "echo 'Build binaries separately before publishing'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Removed build safety guardrail from prepublishOnly.

The prepublishOnly script no longer runs a build; it only echoes a reminder message. This removes an important safety check and increases the risk of publishing an incomplete or broken package if the manual build step is forgotten.

If the platform-specific binary build workflow requires manual coordination across multiple packages, consider adding a validation check instead:

🔎 Suggested validation approach
- "prepublishOnly": "echo 'Build binaries separately before publishing'"
+ "prepublishOnly": "node -e \"if (!require('fs').existsSync('./bin/create-better-t-stack')) throw new Error('Binary not built. Run build script first.')\""

Or use a validation script:

"prepublishOnly": "bun run scripts/validate-build.ts"

This ensures the required artifacts exist before publishing while still allowing flexibility in the build workflow.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"prepublishOnly": "echo 'Build binaries separately before publishing'"
"prepublishOnly": "node -e \"if (!require('fs').existsSync('./bin/create-better-t-stack')) throw new Error('Binary not built. Run build script first.')\""
🤖 Prompt for AI Agents
In apps/cli/package.json around line 68, the prepublishOnly script was changed
to only echo a reminder which removes the build validation guardrail; restore a
safety check by either reverting to running the build (e.g., run the
platform-specific build command used in CI) or invoke a validation script that
asserts required artifacts exist (e.g., "prepublishOnly": "node
./scripts/validate-build.js" or similar), and if using a validation script add
that script to scripts/ and implement checks for the binary/artifact files and
exit non‑zero on failure so publishing is blocked when artifacts are missing.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts (1)

34-68: Add .cwd(serverDir) to the atlas deployments setup command for consistency.

Line 48 runs atlas deployments setup without .cwd(serverDir), unlike all other database providers in this directory (prisma-postgres, neon, supabase). The serverDir parameter is passed but unused. Add .cwd(serverDir) to ensure the Atlas CLI command runs in the correct project context.

apps/cli/src/helpers/database-providers/turso-setup.ts (1)

237-257: Critical logic error: Success reported even when database creation fails after exhausting retries.

If all 5 retry attempts fail with DATABASE_EXISTS errors, the while loop exits normally, and Line 257 logs "setup completed successfully!" even though no database was actually created. This misleads users into thinking setup succeeded when it failed.

🔎 Proposed fix to handle retry exhaustion
 let finalDbName = dbName;
 let attempts = 0;
 const maxAttempts = 5;
+let dbCreated = false;

 while (attempts < maxAttempts) {
   try {
     const tursoConfig = await createTursoDatabase(finalDbName, selectedGroup);
     if (tursoConfig) {
       await writeEnvFile(projectDir, backend, tursoConfig);
     } else {
       await writeEnvFile(projectDir, backend);
     }
+    dbCreated = true;
     break;
   } catch (error) {
     if (error instanceof Error && error.message === "DATABASE_EXISTS") {
       log.warn(`Database "${finalDbName}" already exists, trying alternative name...`);
       finalDbName = `${dbName}-${Math.floor(Math.random() * 1000)}`;
       attempts++;
     } else {
       throw error;
     }
   }
 }

+if (!dbCreated) {
+  throw new Error(`Failed to create database after ${maxAttempts} attempts - all names already exist`);
+}
+
 log.success("Turso database setup completed successfully!");
♻️ Duplicate comments (2)
apps/cli/src/api.ts (1)

134-161: Redundant ternary expressions in config fallback logic.

This issue was already flagged in a previous review. The ternary expressions like options.X ?? (options.defaults ? defaultConfig.X : defaultConfig.X) are redundant since both branches return defaultConfig.X.

apps/cli/src/helpers/database-providers/turso-setup.ts (1)

54-55: Critical security issue: Executing downloaded script without verification (previously flagged).

This security vulnerability was flagged in a previous review and remains unresolved. The code downloads an installation script and executes it directly without verification, creating an arbitrary code execution risk.

Based on learnings, the migration to Bun's $ syntax is correct.

🧹 Nitpick comments (14)
apps/cli/src/helpers/addons/tauri-setup.ts (1)

47-52: Redundant ternary in devUrl fallback.

The final branch hasNext ? "http://localhost:3001" : "http://localhost:3001" returns the same value regardless of condition. This appears to be leftover from refactoring.

🔎 Proposed fix to simplify
     const devUrl =
       hasReactRouter || hasSvelte
         ? "http://localhost:5173"
-        : hasNext
-          ? "http://localhost:3001"
-          : "http://localhost:3001";
+        : "http://localhost:3001";
apps/cli/src/api.ts (3)

31-68: Consider using type alias instead of interface.

Per coding guidelines for TypeScript files, type aliases are preferred over interface declarations.

🔎 Proposed change
-export interface CreateOptions {
+export type CreateOptions = {
   /** Project name or path */
   projectName?: string;
   // ... rest of properties
-}
+};

70-85: Consider using type alias instead of interface.

Same as above - per coding guidelines, prefer type aliases over interface declarations.

🔎 Proposed change
-export interface CreateResult {
+export type CreateResult = {
   /** Whether the project was created successfully */
   success: boolean;
   // ... rest of properties
-}
+};

167-181: Console suppression is a pragmatic workaround but somewhat fragile.

This approach works for synchronous console output but won't capture output from child processes or code that caches console references. Consider documenting this limitation or providing a more robust solution in the future (e.g., passing a quiet/silent mode flag to createProject).

apps/cli/src/cli.ts (2)

85-99: Consider consistency with non-interactive path.

The TUI path directly calls createProject(config) (line 89), while the non-interactive path uses create() from api.ts (line 102). The create() API provides additional handling like console suppression and structured results. This inconsistency may be intentional for TUI (where logs are visible), but worth documenting or unifying.


141-153: TODO placeholder for add command.

The add command is a placeholder. Given this is an experimental PR, this is acceptable, but consider tracking this as a follow-up task.

Would you like me to open an issue to track the implementation of the add command?

apps/cli/src/utils/logger.ts (3)

8-17: Consider using type alias for LogEntry.

Per coding guidelines for TypeScript files, type aliases are preferred over interface declarations.

🔎 Proposed change
-export interface LogEntry {
+export type LogEntry = {
   id: number;
   level: LogLevel;
   message: string;
   timestamp: Date;
-}
+};

19-49: Well-designed event system with React-friendly microtask scheduling.

The use of queueMicrotask for listener notification is a good pattern for React state updates. The per-listener try-catch prevents one faulty listener from breaking the entire chain.

Consider adding a log warning for listener errors in development to aid debugging:

🔎 Optional: Log listener errors in development
         try {
           listener(entry);
         } catch (e) {
-          // Silently ignore listener errors to prevent breaking the log chain
+          // Ignore listener errors to prevent breaking the log chain
+          if (process.env.NODE_ENV === "development") {
+            console.warn("Logger listener error:", e);
+          }
         }

71-84: Potential unbounded memory growth in logs array.

The logs array grows indefinitely. For long-running CLI sessions or TUI usage, this could accumulate significant memory. Consider implementing automatic pruning or a max log limit.

🔎 Proposed enhancement with max log limit
 class Logger {
   private listeners: Set<LogListener> = new Set();
   private logs: LogEntry[] = [];
   private idCounter = 0;
+  private readonly maxLogs = 1000;
 
   // ... in emit method:
   private emit(level: LogLevel, message: string) {
     const entry: LogEntry = {
       id: this.idCounter++,
       level,
       message,
       timestamp: new Date(),
     };
     this.logs.push(entry);
+    
+    // Prune old logs if exceeding limit
+    if (this.logs.length > this.maxLogs) {
+      this.logs = this.logs.slice(-this.maxLogs);
+    }
apps/cli/src/helpers/addons/ultracite-setup.ts (1)

121-126: Inconsistent error logging pattern.

Line 124 uses console.error(pc.red(...)) while line 122 uses log.error(...). Other setup files in this PR (e.g., fumadocs-setup.ts, prisma-postgres-setup.ts) consistently use only log.error for error messages.

🔎 Proposed fix for consistency
   } catch (error) {
     log.error("Failed to set up Ultracite");
     if (error instanceof Error) {
-      console.error(pc.red(error.message));
+      log.error(error.message);
     }
   }
apps/cli/src/helpers/core/db-setup.ts (1)

2-2: Incomplete migration to new logger.

This file still imports consola (line 2) and uses it at line 186, while other setup files in this PR have migrated to the new log utility from ../../utils/logger. Consider updating for consistency.

🔎 Proposed fix
 import path from "node:path";
-import consola from "consola";
+import { log } from "../../utils/logger";
 import fs from "fs-extra";
-import pc from "picocolors";
 import type { AvailableDependencies } from "../../constants";

And at line 186:

   } catch (error) {
     if (error instanceof Error) {
-      consola.error(pc.red(error.message));
+      log.error(error.message);
     }
   }
apps/cli/src/helpers/database-providers/neon-setup.ts (1)

34-37: Fragile string manipulation for success messages.

The transformation stepText.replace("...", "").replace("ing ", "ed ") is brittle and may produce unexpected results for certain inputs (e.g., "Configuring something" → "Configured somethng").

Consider using explicit success messages or a more robust pattern.

🔎 Alternative approach
 async function executeNeonCommand(
   packageManager: PackageManager,
   commandArgsString: string,
-  stepText?: string,
+  options?: { stepText?: string; successText?: string },
 ) {
   try {
     const fullCommand = getPackageExecutionCommand(packageManager, commandArgsString);
 
-    if (stepText) log.step(stepText);
+    if (options?.stepText) log.step(options.stepText);
     const result = await $`${{ raw: fullCommand }}`.text();
-    if (stepText) log.success(stepText.replace("...", "").replace("ing ", "ed ").trim());
+    if (options?.successText) log.success(options.successText);
     return { stdout: result };
   } catch (error) {
-    log.error(`Failed: ${stepText || "Command execution"}`);
+    log.error(`Failed: ${options?.stepText || "Command execution"}`);
     throw error;
   }
 }
apps/cli/src/helpers/database-providers/turso-setup.ts (2)

249-249: Use timestamp or counter instead of random suffix for better uniqueness.

The random suffix (0-999) could still result in collisions. Consider using a timestamp or incrementing counter for guaranteed uniqueness across retries.

🔎 Proposed alternatives

Option 1: Timestamp-based suffix

-      finalDbName = `${dbName}-${Math.floor(Math.random() * 1000)}`;
+      finalDbName = `${dbName}-${Date.now()}`;

Option 2: Counter-based suffix

-      finalDbName = `${dbName}-${Math.floor(Math.random() * 1000)}`;
+      finalDbName = `${dbName}-${attempts + 1}`;

81-84: Consider using standard function expression for map callback.

The coding guidelines prefer standard function declarations over arrow functions. While this typically applies to top-level functions, the callback could be refactored for consistency.

🔎 Alternative syntax
-const groups = lines.slice(1).map((line: string) => {
+const groups = lines.slice(1).map(function(line: string) {
   const [name, locations, version, status] = line.trim().split(/\s{2,}/);
   return { name, locations, version, status };
 });

As per coding guidelines, standard function declarations are preferred.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1fcb7b and d1f8ac1.

📒 Files selected for processing (23)
  • apps/cli/scripts/build.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/render-title.ts
  • apps/cli/src/utils/sponsors.ts
💤 Files with no reviewable changes (2)
  • apps/cli/src/utils/render-title.ts
  • apps/cli/src/helpers/core/command-handlers.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/scripts/build.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.serve()` which supports WebSockets, HTTPS, and routes instead of `express`

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.sql` for Postgres instead of `pg` or `postgres.js`

Applied to files:

  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer `Bun.file` over `node:fs` readFile/writeFile methods

Applied to files:

  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` module for SQLite instead of `better-sqlite3`

Applied to files:

  • apps/cli/src/helpers/database-providers/supabase-setup.ts
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, when passing the Ultracite CLI --integrations flag, supply git hooks as a single space-separated string (e.g., gitHooks.join(" ")) rather than spreading the array like other Ultracite flags. This has been tested and confirmed to work. Ensure the code uses a single string created by joining the gitHooks array with spaces for the --integrations argument.

Applied to files:

  • apps/cli/src/helpers/addons/ultracite-setup.ts
🧬 Code graph analysis (13)
apps/cli/src/helpers/addons/tauri-setup.ts (1)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts (2)
apps/cli/src/utils/command-exists.ts (1)
  • commandExists (3-16)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/project-directory.ts (1)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/database-providers/turso-setup.ts (2)
apps/cli/src/utils/command-exists.ts (1)
  • commandExists (3-16)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/database-providers/neon-setup.ts (2)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/core/db-setup.ts (7)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/types.ts (1)
  • ProjectConfig (67-67)
apps/cli/src/helpers/database-providers/turso-setup.ts (1)
  • setupTurso (179-266)
apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts (1)
  • setupPrismaPostgres (113-159)
apps/cli/src/helpers/database-providers/neon-setup.ts (1)
  • setupNeonPostgres (136-171)
apps/cli/src/helpers/database-providers/supabase-setup.ts (1)
  • setupSupabase (121-171)
apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts (1)
  • setupMongoDBAtlas (109-148)
apps/cli/src/api.ts (3)
apps/cli/src/constants.ts (1)
  • getDefaultConfig (106-115)
apps/cli/src/helpers/core/create-project.ts (1)
  • createProject (36-134)
apps/cli/src/utils/generate-reproducible-command.ts (1)
  • generateReproducibleCommand (3-53)
apps/cli/src/cli.ts (7)
apps/cli/src/utils/get-latest-cli-version.ts (1)
  • getLatestCLIVersion (13-27)
apps/cli/src/tui/app.tsx (1)
  • renderTui (524-541)
apps/cli/test/test-utils.ts (14)
  • Frontend (176-176)
  • Backend (174-174)
  • Runtime (175-175)
  • Database (172-172)
  • ORM (173-173)
  • Auth (179-179)
  • Payments (180-180)
  • Addons (177-177)
  • API (181-181)
  • Examples (178-178)
  • DatabaseSetup (184-184)
  • WebDeploy (182-182)
  • ServerDeploy (183-183)
  • PackageManager (171-171)
apps/cli/src/helpers/core/create-project.ts (1)
  • createProject (36-134)
apps/cli/src/utils/generate-reproducible-command.ts (1)
  • generateReproducibleCommand (3-53)
apps/cli/src/api.ts (1)
  • create (108-201)
apps/cli/src/utils/open-url.ts (1)
  • openUrl (3-17)
apps/cli/src/helpers/addons/ruler-setup.ts (3)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts (3)
apps/cli/test/test-utils.ts (1)
  • PackageManager (171-171)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/helpers/database-providers/supabase-setup.ts (3)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/types.ts (1)
  • ProjectConfig (67-67)
apps/cli/src/helpers/addons/fumadocs-setup.ts (2)
apps/cli/src/types.ts (1)
  • TEMPLATE_VALUES (43-43)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/addons/ultracite-setup.ts (3)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/types.ts (1)
  • ProjectConfig (67-67)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
🔇 Additional comments (28)
apps/cli/src/utils/sponsors.ts (2)

1-4: LGTM! Migration to centralized logger is clean.

The imports and logger usage align well with the new logging system. The transition from @clack/prompts to the internal logger follows the patterns established across the codebase.


43-55: LGTM! Fetch sponsors function correctly uses logger.

The progression from log.step → error handling with log.errorlog.success provides clear user feedback during the async operation.

apps/cli/src/helpers/addons/tauri-setup.ts (2)

2-8: LGTM! Correct migration to Bun-based execution.

Import of $ from bun and log from the centralized logger aligns with the coding guidelines for using Bun.$ template literal syntax instead of execa.


79-86: LGTM! Bun execution and error handling look correct.

The ${{ raw: tauriInitCommand }} pattern with .cwd() and .env() chaining is the appropriate Bun idiom. Error handling provides user feedback via the logger. Based on learnings, this correctly uses Bun.$ template literal syntax instead of execa.

apps/cli/src/helpers/addons/tui-setup.ts (2)

2-11: LGTM! Clean migration to Bun-based execution with template parameter.

The function signature update to accept an explicit template parameter with a sensible default aligns with the removal of interactive prompts. Uses Bun.$ as per coding guidelines.


24-34: LGTM! Execution and error handling are consistent with other addon setups.

The pattern of using log.error for the high-level message and console.error with pc.red for the detailed error message is consistent with wxt-setup.ts and ruler-setup.ts.

apps/cli/src/helpers/addons/wxt-setup.ts (2)

2-11: LGTM! Consistent migration to Bun-based execution.

The import of $ from bun, logger integration, and updated function signature with template parameter follows the same pattern as other addon setup files. Uses Bun.$ as per coding guidelines.


24-48: LGTM! Execution flow and error handling are well-structured.

The command execution with .cwd() and .env({ CI: "true" }) chaining, followed by package.json modifications and appropriate logging, provides a clean setup flow.

apps/cli/src/cli.ts (2)

1-12: LGTM! CLI entry point with Commander setup.

The shebang #!/usr/bin/env bun correctly indicates Bun-based execution. Imports are well-organized with clear separation of concerns.


155-181: LGTM! Dynamic import for openUrl is appropriate.

Using dynamic imports for the openUrl utility in the docs and builder commands is a reasonable approach for commands that are called infrequently.

apps/cli/src/helpers/addons/ruler-setup.ts (3)

2-7: LGTM! Migration to Bun-based execution.

The import of $ from bun and log from the centralized logger follows the established pattern. Uses Bun.$ as per coding guidelines.


37-40: LGTM! Updated function signature with agents parameter.

The removal of interactive prompt flow in favor of an explicit agents parameter with sensible defaults aligns with the broader refactoring pattern across addon setups.


77-95: LGTM! Command execution and error handling.

The Bun command execution pattern with .cwd() and .env({ CI: "true" }) is consistent with other addon setups. Error handling provides appropriate user feedback.

apps/cli/src/utils/logger.ts (1)

86-96: LGTM! Clean singleton pattern and convenience wrapper.

The global logger instance and log convenience object provide a simple API for consumers while maintaining the full Logger interface for advanced use cases.

apps/cli/src/helpers/addons/fumadocs-setup.ts (1)

1-67: LGTM! Clean migration to Bun-based execution.

The refactoring from execa to Bun.$ and the introduction of a parameterized template argument with TEMPLATE_VALUES mapping aligns well with the PR's goal of supporting a programmatic API. The CI: "true" env ensures non-interactive execution.

One minor note: the catch block silently continues after logging errors. This is acceptable for a setup helper where failure shouldn't block the overall CLI flow, but consider whether the caller should be notified of partial failures.

apps/cli/src/helpers/core/db-setup.ts (1)

17-23: LGTM on the new DbSetupOptions type and mode propagation.

The type alias pattern is correctly used, and the mode is properly extracted with a sensible default and propagated to all database provider setup functions.

apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts (1)

1-159: LGTM! Well-structured migration to Bun-based execution.

The refactoring cleanly separates:

  • PrismaPostgresSetupOptions type for parameterized configuration
  • setupWithCreateDb for database creation logic
  • Proper fallback to manual setup on errors

The Bun $ usage with .cwd() and .text() is correct for capturing command output.

apps/cli/src/helpers/database-providers/supabase-setup.ts (1)

1-171: LGTM! Clean migration with proper stdout handling.

The Supabase setup correctly:

  • Uses SupabaseSetupOptions type alias
  • Captures stdout from supabase start to extract the DB URL
  • Maintains proper fallback to manual instructions when extraction fails
apps/cli/src/utils/project-directory.ts (1)

65-91: LGTM on setupProjectDirectory.

The function correctly uses the new logger for progress reporting and maintains proper directory clearing/creation logic.

apps/cli/src/helpers/database-providers/neon-setup.ts (1)

136-171: LGTM on setupNeonPostgres refactoring.

The function properly handles the NeonSetupOptions with sensible defaults for mode, setupMethod, projectName, and regionId. The fallback to manual setup on errors is well implemented.

apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts (1)

109-148: LGTM on setupMongoDBAtlas refactoring.

The function correctly uses MongoDBAtlasSetupOptions with proper defaults and graceful fallback to manual setup. The separation between auto and manual modes is clean.

apps/cli/src/helpers/addons/ultracite-setup.ts (1)

96-102: Line 101: --integrations argument format may need adjustment.

According to learnings from this repository, the Ultracite CLI's --integrations flag should receive a single space-separated string rather than individual arguments. Consider changing line 101 to: ultraciteArgs.push("--integrations", ["husky", "lint-staged"].join(" ")); to ensure the flag receives the value in the expected format.

apps/cli/src/helpers/database-providers/turso-setup.ts (6)

95-105: Verify if auto-selection of first group is appropriate for all scenarios.

The function now automatically selects the first available Turso group without user confirmation. This removes the ability for users to choose a specific group when multiple are available. Confirm this aligns with the intended non-interactive TUI flow.

Consider whether users in certain scenarios (e.g., multiple groups with different purposes) should be able to specify their preferred group via the TursoSetupOptions.


26-33: LGTM: Correct migration to Bun's text() method.

The function correctly uses .text() for output parsing and maintains proper error handling.

Based on learnings, migration from execa to Bun's $ is correct.


35-45: LGTM: Proper use of logging and error handling.

The login flow correctly uses the log utility and returns a boolean to indicate success/failure, enabling proper fallback handling in the caller.


16-20: LGTM: Well-designed options type.

The TursoSetupOptions type follows TypeScript guidelines (type alias instead of interface) and provides a clean API for configuring setup behavior.


179-190: LGTM: Clean option-driven flow with proper fallback.

The function signature correctly uses the options parameter with sensible defaults, and the manual mode handling properly writes the env file and displays instructions.


223-229: LGTM: Robust login flow with fallback handling.

The login attempt with fallback to manual setup ensures users aren't blocked if authentication fails.

Comment on lines +9 to +35
type RulerAgent =
| "amp"
| "copilot"
| "claude"
| "codex"
| "cursor"
| "windsurf"
| "cline"
| "aider"
| "firebase"
| "gemini-cli"
| "junie"
| "kilocode"
| "opencode"
| "crush"
| "zed"
| "qwen"
| "amazonqcli"
| "augmentcode"
| "firebender"
| "goose"
| "jules"
| "kiro"
| "openhands"
| "roo"
| "trae"
| "warp";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

@intellectronica/ruler supported agents

💡 Result:

Here’s a concise list of AI agents Ruler ( @intellectronica/ruler ) supports (files/config it writes shown when available). Sources: [1][2][3].

  • AGENTS.md (pseudo‑agent / root AGENTS.md). [1][2]
  • GitHub Copilot — .github/copilot-instructions.md (and .vscode/mcp.json). [1][2]
  • Claude / Claude Code — CLAUDE.md (and .mcp.json / claude_desktop_config.json). [1][2]
  • OpenAI Codex CLI — AGENTS.md / ~/.codex/config.json / .codex/config.toml. [1][2][3]
  • Jules. [1][2]
  • Cursor — .cursor/rules/ruler_cursor_instructions(.mdc) and .cursor/mcp.json. [1][2][3]
  • Windsurf — .windsurf/rules/ruler_windsurf_instructions.md (and MCP paths). [1][2]
  • Cline — .clinerules. [1][2]
  • Amp. [2]
  • Amazon Q CLI — .amazonq/rules/ruler_q_rules.md and .amazonq/mcp.json. [2]
  • Aider — AGENTS.md / ruler_aider_instructions.md and .aider.conf.yml (.mcp.json). [1][2][3]
  • Firebase Studio — .idx/airules.md. [1][2]
  • Open Hands — .openhands/microagents/repo.md and .openhands/config.toml. [1][2]
  • Gemini CLI — GEMINI.md and .gemini/settings.json. [1][2]
  • Junie — .junie/guidelines.md. [1][2]
  • AugmentCode — .augment/rules/ruler_augment_instructions.md. [1][2]
  • Kilo Code — .kilocode/rules/ruler_kilocode_instructions.md and .kilocode/mcp.json. [1][2]
  • OpenCode / opencode — AGENTS.md and opencode.json / ~/.config/opencode/opencode.json. [1][2]
  • Goose — .goosehints. [2]
  • Qwen Code — AGENTS.md and .qwen/settings.json. [2]
  • RooCode — AGENTS.md and .roo/mcp.json. [2]
  • Zed — AGENTS.md and .zed/settings.json. [2]
  • Trae AI — .trae/rules/project_rules.md. [2]
  • Warp — WARP.md. [2]
  • Kiro — .kiro/steering/ruler_kiro_instructions.md and .kiro/settings/mcp.json. [2]
  • Firebender — firebender.json (rules + MCP same file). [2]

Notes: implementations and exact file names/paths vary slightly between releases; see the Ruler docs and GitHub repo for the most current list and per-agent details. [1][2][3]

Sources

  1. Ruler — AI Expertise (intellectronica) — Ruler docs. [online].
  2. GitHub — intellectronica/ruler repository (Supported AI Agents section). [online].
  3. npm — @intellectronica/ruler package page. [online].

Remove unsupported agent "crush" from RulerAgent type.

The type uses a good approach for type safety, but the list includes "crush," which is not a supported agent in the @intellectronica/ruler library. The remaining 24 agents (amp, copilot, claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie, kilocode, opencode, zed, qwen, amazonqcli, augmentcode, firebender, goose, jules, kiro, openhands, roo, trae, warp) are all verified as supported by Ruler.

🤖 Prompt for AI Agents
In apps/cli/src/helpers/addons/ruler-setup.ts around lines 9 to 35, the
RulerAgent union includes an unsupported agent "crush"; remove the "crush" entry
from the union type so the type only lists the supported agents (amp, copilot,
claude, codex, cursor, windsurf, cline, aider, firebase, gemini-cli, junie,
kilocode, opencode, zed, qwen, amazonqcli, augmentcode, firebender, goose,
jules, kiro, openhands, roo, trae, warp) and save the file.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
apps/cli/src/tui/app.tsx (3)

690-703: Use path.join instead of string concatenation for path construction.

Line 696 uses string concatenation with / which won't work correctly on Windows. This issue was flagged in previous reviews.

🔎 Proposed fix
+import path from "node:path";
+
 // In handleComplete:
 const cfg: ProjectConfig = {
   ...defaultConfig,
   ...config,
   projectName: config.projectName ?? "my-app",
-  projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
+  projectDir: path.join(process.cwd(), config.projectName ?? "my-app"),
   relativePath: config.projectName ?? "my-app",

Based on past review comments.


780-791: Use path.join for projectDir path construction.

Line 785 also uses string concatenation with / for path construction. This should be updated along with line 696 to use path.join for cross-platform compatibility.

🔎 Proposed fix
                 {currentStep.type === "input" && (
                   <InputPrompt
                     onSubmit={(v) => {
                       updateConfig(currentStep.id, v);
                       if (currentStep.id === "projectName") {
-                        updateConfig("projectDir", process.cwd() + "/" + v);
+                        updateConfig("projectDir", path.join(process.cwd(), v));
                         updateConfig("relativePath", v);
                       }
                       goNext();
                     }}

Based on past review comments.


524-560: Remove process.exit(0) calls to allow graceful shutdown.

While the Promise now calls resolve(), the process.exit(0) on line 537 terminates the process immediately, preventing any cleanup code in the caller from executing. Additionally, line 635 in the App component's keyboard handler bypasses the Promise entirely with a direct process.exit(0) call.

Remove these process.exit(0) calls and let the caller decide when to exit, or document that this function terminates the process.

🔎 Proposed fix
 const handleExit = () => {
   // Clean up the renderer before exiting (following opencode pattern)
   try {
     renderer.destroy();
   } catch {
     // Ignore errors during cleanup
   }
   options.onCancel();
   resolve();
-  process.exit(0);
 };

Also update the keyboard handler in the App component (line 635):

 useKeyboard((key) => {
   if (key.ctrl && key.name === "c") props.onExit();
   // Exit on any key when done
   if (phase === "done" && key.name !== "c") {
-    process.exit(0);
+    props.onExit();
   }
 });

Based on past review comments.

🧹 Nitpick comments (2)
apps/cli/src/tui/app.tsx (2)

709-714: Improve error handling and user feedback.

When onComplete throws an error, the phase remains stuck on "creating" and only the status text changes. Consider setting the phase to "done" or adding an "error" phase to provide clearer feedback and allow the user to exit gracefully.

🔎 Proposed enhancement
     try {
       await props.onComplete(cfg);
       setPhase("done");
     } catch (error) {
       setCreationStatus(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
+      // Allow user to exit after error
+      setPhase("done");
     }

932-932: Consider importing version from package.json.

The hardcoded version string could get out of sync with the actual package version. Consider importing it from package.json or using a build-time constant.

Possible approach
import packageJson from "../../package.json";
const VERSION = packageJson.version;

Note: This requires enabling resolveJsonModule in tsconfig.json if not already enabled.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1f8ac1 and ffee16a.

📒 Files selected for processing (1)
  • apps/cli/src/tui/app.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/tui/app.tsx
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/tui/app.tsx
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/tui/app.tsx
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, the Ultracite CLI's `--integrations` flag requires git hooks to be passed as a single space-separated string (e.g., `gitHooks.join(" ")`) rather than using the spread operator like other Ultracite flags. This has been tested and confirmed to work.

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Always add 'use node'; to the top of files containing actions that use Node.js built-in modules

Applied to files:

  • apps/cli/src/tui/app.tsx
🔇 Additional comments (1)
apps/cli/src/tui/app.tsx (1)

1-1156: Well-structured TUI implementation with comprehensive step configuration.

The overall implementation is solid:

  • Comprehensive STEPS configuration matching all required prompts
  • Clean component separation (Spinner, LogDisplay, StatusBar, prompt components)
  • Proper React hooks usage throughout
  • Good keyboard navigation support
  • Clear phase management (prompts → creating → done)

The main concerns are the type declarations, process exit handling, and path concatenation issues flagged in other comments.

Comment on lines 42 to 56
export interface TuiOptions {
initialConfig?: Partial<ProjectConfig>;
onComplete: (config: ProjectConfig) => Promise<void>;
onCancel: () => void;
}

interface StepConfig {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Convert interfaces to type aliases.

The coding guidelines specify using TypeScript type aliases instead of interface declarations.

🔎 Proposed fix
-export interface TuiOptions {
+export type TuiOptions = {
   initialConfig?: Partial<ProjectConfig>;
   onComplete: (config: ProjectConfig) => Promise<void>;
   onCancel: () => void;
-}
+};

-interface StepConfig {
+type StepConfig = {
   id: string;
   title: string;
   type: "input" | "select" | "multiselect" | "confirm";
   skip?: (config: any) => boolean;
   getDefault?: (config: any) => any;
   getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
   options?: { name: string; value: string; hint?: string }[];
-}
+};

As per coding guidelines.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface TuiOptions {
initialConfig?: Partial<ProjectConfig>;
onComplete: (config: ProjectConfig) => Promise<void>;
onCancel: () => void;
}
interface StepConfig {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
}
export type TuiOptions = {
initialConfig?: Partial<ProjectConfig>;
onComplete: (config: ProjectConfig) => Promise<void>;
onCancel: () => void;
};
type StepConfig = {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
};

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

237-257: Critical bug: Retry exhaustion is not handled.

If all retry attempts fail with DATABASE_EXISTS errors, the while loop exits normally without executing the break statement. This means:

  1. No env file is written (the writeEnvFile calls on lines 241-244 never execute)
  2. Line 257 claims "setup completed successfully" even though no database was created
  3. The user has no configuration and will encounter runtime errors
🔎 Proposed fix
+   let setupSucceeded = false;
+
    while (attempts < maxAttempts) {
      try {
        const tursoConfig = await createTursoDatabase(finalDbName, selectedGroup);
        if (tursoConfig) {
          await writeEnvFile(projectDir, backend, tursoConfig);
        } else {
          await writeEnvFile(projectDir, backend);
        }
+       setupSucceeded = true;
        break;
      } catch (error) {
        if (error instanceof Error && error.message === "DATABASE_EXISTS") {
          log.warn(`Database "${finalDbName}" already exists, trying alternative name...`);
          finalDbName = `${dbName}-${Math.floor(Math.random() * 1000)}`;
          attempts++;
        } else {
          throw error;
        }
      }
    }

+   if (!setupSucceeded) {
+     throw new Error(`Failed to create database after ${maxAttempts} attempts - all names already exist`);
+   }
+
    log.success("Turso database setup completed successfully!");
apps/cli/test/test-utils.ts (1)

149-154: Pass the expectError configuration flag from test config to the create() API call.

The test cases are correctly configured with expectError: true, but the runTRPCTest function never forwards this flag to the create() API (lines 99–117). This means create() doesn't know it should trigger validation errors, causing it to return success: true when tests expect success: false. Add expectError: config.expectError to the create() function call parameters.

♻️ Duplicate comments (13)
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

54-55: Critical security issue: Executing downloaded script without verification.

This security vulnerability was already flagged in a previous review. The code downloads an installation script from the internet and executes it with bash without verification, which could allow arbitrary code execution if the download is compromised.

Please refer to the previous review comment for recommended security improvements including checksum verification or user confirmation prompts.

apps/cli/src/helpers/core/git.ts (1)

20-21: Add error handling for git add and commit operations.

These commands use .quiet() but not .nothrow(), meaning they will throw unhandled errors on failure. This is inconsistent with the explicit error handling pattern used for git init above.

apps/cli/src/helpers/addons/ruler-setup.ts (1)

9-35: Remove unsupported agent "crush" from RulerAgent type.

The agent "crush" on line 23 is not a supported agent in the @intellectronica/ruler library according to web search verification. Remove it from the type definition.

apps/cli/scripts/publish.ts (2)

21-24: Tag parsing can capture undefined or wrong values.

When --tag is the last argument or followed by another flag, process.argv[indexOf + 1] will be undefined or capture the wrong value. This was previously flagged.

🔎 Proposed fix
 const dryRun = process.argv.includes("--dry-run");
-const tag = process.argv.includes("--tag")
-  ? process.argv[process.argv.indexOf("--tag") + 1]
-  : "latest";
+const tagIndex = process.argv.indexOf("--tag");
+const tag = 
+  tagIndex !== -1 && 
+  tagIndex + 1 < process.argv.length && 
+  !process.argv[tagIndex + 1].startsWith("--")
+    ? process.argv[tagIndex + 1]
+    : "latest";

96-103: Direct assignment replaces existing optionalDependencies.

Line 101 uses direct assignment, which will remove any existing optionalDependencies entries (such as @opentui/core-* platform packages). This was previously flagged.

🔎 Proposed fix to merge instead of replace
 const optionalDeps: Record<string, string> = {};
 for (const built of builtPackages) {
   optionalDeps[built.name] = built.version;
 }

-pkg.optionalDependencies = optionalDeps;
+pkg.optionalDependencies = {
+  ...(pkg.optionalDependencies || {}),
+  ...optionalDeps,
+};
 await Bun.write("./package.json", JSON.stringify(pkg, null, 2) + "\n");
.github/workflows/pr-preview.yaml (2)

104-117: Critical: Working directory not restored after publishing platform packages.

After the loop completes at line 115, the working directory remains at apps/cli/dist (or a subdirectory). The subsequent steps at lines 120 and 125 use cd apps/cli and cd packages/create-bts, which expect to run from the repository root. This was previously flagged.

🔎 Proposed fix using subshell
       - name: Publish CLI platform packages to NPM
         run: |
+          (
           cd apps/cli/dist
           ls -la
           for dir in */; do
             if [ -f "$dir/package.json" ]; then
               echo "Publishing $dir..."
               cd "$dir"
               bun publish --access public --tag ${{ steps.version.outputs.tag }}
               cd ..
             fi
           done
+          )
         env:
           NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

104-117: Major: No error handling in platform package publish loop.

The loop continues even if bun publish fails. Without set -e, the step might succeed despite publish failures, leading to incomplete preview releases. This was previously flagged.

🔎 Proposed fix with fail-fast behavior
       - name: Publish CLI platform packages to NPM
         run: |
+          set -e
           cd apps/cli/dist
           ls -la
           for dir in */; do
             if [ -f "$dir/package.json" ]; then
               echo "Publishing $dir..."
               cd "$dir"
               bun publish --access public --tag ${{ steps.version.outputs.tag }}
               cd ..
             fi
           done
         env:
           NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
apps/cli/src/tui/app.tsx (3)

42-56: Convert interfaces to type aliases.

The coding guidelines specify using TypeScript type aliases instead of interface declarations.

🔎 Proposed fix
-export interface TuiOptions {
+export type TuiOptions = {
   initialConfig?: Partial<ProjectConfig>;
   onComplete: (config: ProjectConfig) => Promise<void>;
   onCancel: () => void;
-}
+};

-interface StepConfig {
+type StepConfig = {
   id: string;
   title: string;
   type: "input" | "select" | "multiselect" | "confirm";
   skip?: (config: any) => boolean;
   getDefault?: (config: any) => any;
   getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
   options?: { name: string; value: string; hint?: string }[];
-}
+};

As per coding guidelines.


770-777: Use path.join for projectDir path construction.

String concatenation with / won't work correctly on Windows. Use path.join for cross-platform compatibility.

🔎 Proposed fix
+import path from "node:path";
+
 const handleComplete = useCallback(async () => {
   const defaultConfig = getDefaultConfig();
+  const projectName = config.projectName ?? "my-app";
   const cfg: ProjectConfig = {
     ...defaultConfig,
     ...config,
-    projectName: config.projectName ?? "my-app",
-    projectDir: process.cwd() + "/" + (config.projectName ?? "my-app"),
-    relativePath: config.projectName ?? "my-app",
+    projectName,
+    projectDir: path.join(process.cwd(), projectName),
+    relativePath: projectName,

866-875: Use path.join instead of string concatenation for paths.

String concatenation with / won't work correctly on Windows. Use path.join for cross-platform compatibility.

🔎 Proposed fix
+import path from "node:path";
+
                 <InputPrompt
                   onSubmit={(v) => {
                     updateConfig(currentStep.id, v);
                     if (currentStep.id === "projectName") {
-                      updateConfig("projectDir", process.cwd() + "/" + v);
+                      updateConfig("projectDir", path.join(process.cwd(), v));
                       updateConfig("relativePath", v);
                     }
                     goNext();
                   }}
apps/cli/package.json (3)

73-74: Version mismatch between @opentui/core and platform-specific packages.

The main dependency uses "@opentui/core": "^0.1.62" but the optional platform bindings pin to 0.1.63. This mismatch could cause resolution conflicts or runtime incompatibilities.

🔎 Suggested fix
-  "@opentui/core": "^0.1.62",
-  "@opentui/react": "^0.1.62",
+  "@opentui/core": "^0.1.63",
+  "@opentui/react": "^0.1.63",

Or downgrade platform packages to 0.1.62 for consistency.

Also applies to: 101-106


42-54: Publishing TypeScript source files will break package consumers.

The package configuration now publishes the src directory and points main, types, and exports to TypeScript source files (./src/index.ts). This configuration will fail for published packages because:

  1. Node.js cannot execute .ts files directly
  2. Most consumers expect pre-compiled JavaScript with separate .d.ts type definitions
  3. TypeScript source requires exact compiler configuration match
🔎 Expected configuration for published packages
  "files": [
    "bin",
-   "src",
+   "dist",
    "templates"
  ],
- "main": "./src/index.ts",
- "types": "./src/index.ts",
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
  "exports": {
    ".": {
-     "types": "./src/index.ts",
-     "import": "./src/index.ts"
+     "types": "./dist/index.d.ts",
+     "import": "./dist/index.js"
    }
  }

Ensure the build process outputs compiled files to dist/ and update prepublishOnly to validate artifacts exist.


68-68: Removed build safety guardrail from prepublishOnly.

The prepublishOnly script no longer runs a build; it only echoes a reminder message. This removes an important safety check and increases the risk of publishing an incomplete or broken package if the manual build step is forgotten.

🔎 Suggested validation approach
- "prepublishOnly": "echo 'Build binaries separately before publishing'"
+ "prepublishOnly": "node -e \"if (!require('fs').existsSync('./bin/create-better-t-stack')) throw new Error('Binary not built. Run build script first.')\""

Or use a validation script that checks for required artifacts before allowing publish.

🧹 Nitpick comments (11)
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

90-90: Consider using logger for consistency.

Direct use of console.error here is inconsistent with the rest of the file which uses the log utility. While this might be intentional to preserve the full error object output, consider using log.error() for consistency or adding a comment explaining why console.error is preferred here.

🔎 Suggested change
-    console.error("Error fetching Turso groups:", error);
+    // Log detailed error for debugging
+    if (error instanceof Error) {
+      log.error(`Error fetching Turso groups: ${error.message}`);
+    }
apps/cli/src/helpers/core/add-addons.ts (1)

76-78: Consider using the centralized logger for consistency.

Other files in this PR (e.g., ruler-setup.ts, addons-setup.ts) use the new centralized log helper from ../../utils/logger. Using console.log directly here creates inconsistency with the broader logging migration.

🔎 Suggested change for consistency
+import { log } from "../../utils/logger";
 import pc from "picocolors";
 ...
-      console.log(
-        pc.yellow(`ℹ Run ${pc.bold(`${config.packageManager} install`)} to install dependencies`),
-      );
+      log.info(`Run ${pc.bold(`${config.packageManager} install`)} to install dependencies`);
apps/cli/scripts/build.ts (2)

27-29: Consider using Bun.file for reading package.json.

Per coding guidelines, prefer Bun.file over node:fs readFile methods. Since this is a Bun-specific build script, using Bun.file().json() would be more idiomatic.

🔎 Suggested change
-import fs from "node:fs";
...
-const pkg = JSON.parse(fs.readFileSync("./package.json", "utf-8"));
+const pkg = await Bun.file("./package.json").json();

Note: If you need fs for other operations like existsSync, rmSync, mkdirSync, and statSync, you may keep the import but consider using the Bun API where possible.


69-77: Simplify by using top-level import for $.

The dynamic import of $ from "bun" is unnecessary since the entire script is Bun-specific (shebang #!/usr/bin/env bun). Import it at the top level for clarity.

🔎 Suggested change
 import path from "node:path";
 import fs from "node:fs";
 import { fileURLToPath } from "node:url";
+import { $ } from "bun";
...
 // Install all platform binaries for opentui (required for cross-compilation)
 if (!singleFlag) {
-  const { $ } = await import("bun");
   console.log("Installing all platform binaries for @opentui/core...\n");
   try {
     await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`.quiet();
apps/cli/src/utils/get-latest-cli-version.ts (1)

13-13: Consider renaming for clarity.

The function name getLatestCLIVersion suggests it fetches the latest version from npm, but it actually returns the current installed/compiled version. Consider renaming to getCLIVersion or getCurrentCLIVersion for clarity.

apps/cli/src/constants.ts (1)

46-82: Complex but necessary fallback chain for PKG_ROOT resolution.

The multiple fallback paths handle various execution contexts (npm install, dev mode, different binary locations). Consider adding a debug log or comment explaining when each fallback is expected to match to aid future debugging.

🔎 Optional: Add context comments for fallback paths
   if (isCompiledBinary()) {
-    // First try: find main package in node_modules (production npm install)
+    // First try: production npm install - binary is in node_modules/@better-t-stack/cli-{platform}/bin/
     const mainPkg = findMainPackage();
     if (mainPkg) {
       return mainPkg;
     }

-    // Second try: development mode - binary is in dist/create-better-t-stack-{platform}-{arch}/bin/
+    // Second try: local dev build - binary at dist/{platform-dir}/bin/, templates at ../../templates
     ...
apps/cli/src/helpers/database-providers/neon-setup.ts (1)

34-36: Fragile text transformation for success messages.

The string manipulation at line 36 assumes specific patterns ("...", "ing "). If stepText doesn't match these patterns, the success message will be malformed.

🔎 More robust success message handling
-    if (stepText) log.step(stepText);
     const result = await $`${{ raw: fullCommand }}`.text();
-    if (stepText) log.success(stepText.replace("...", "").replace("ing ", "ed ").trim());
+    if (stepText) {
+      log.step(stepText);
+      const successMsg = stepText.replace("...", "").replace(/ing\s+/, "ed ").trim();
+      log.success(successMsg || "Command completed successfully");
+    }
     return { stdout: result };
apps/cli/src/helpers/addons/tauri-setup.ts (1)

47-52: Redundant devUrl fallback logic.

Lines 49-52 show that when hasNext is true, the URL is http://localhost:3001, and the final fallback is also http://localhost:3001. This makes the hasNext check redundant in this ternary chain.

🔎 Simplify devUrl logic
 const devUrl =
   hasReactRouter || hasSvelte
     ? "http://localhost:5173"
-    : hasNext
-      ? "http://localhost:3001"
-      : "http://localhost:3001";
+    : "http://localhost:3001";

Or if there's a future intention to differentiate Next.js, add a comment explaining the structure.

apps/cli/src/helpers/addons/wxt-setup.ts (1)

43-47: Inconsistent error logging pattern.

Line 44 uses log.error() while line 46 uses console.error() for the detailed error message. For consistency, consider using log.error() for both, or document why console.error is preferred for the detailed message.

🔎 Consistent error logging
   } catch (error) {
     log.error("Failed to set up WXT");
     if (error instanceof Error) {
-      console.error(pc.red(error.message));
+      log.error(error.message);
     }
   }

Note: This assumes the logger handles color formatting. If console.error is intentional for stack traces, add a comment explaining the distinction.

apps/cli/src/utils/logger.ts (1)

24-83: Remove explicit return types.

The coding guidelines specify not using explicit return types. Lines 24, 71, and 81 have explicit return type annotations that should be removed for consistency with project conventions.

🔎 Proposed fix
- subscribe(listener: LogListener): () => void {
+ subscribe(listener: LogListener) {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

- getLogs(): LogEntry[] {
+ getLogs() {
    return [...this.logs];
  }

- getRecentLogs(count: number = 15): LogEntry[] {
+ getRecentLogs(count = 15) {
    return this.logs.slice(-count);
  }

As per coding guidelines.

apps/cli/src/index.ts (1)

50-51: Consider using formal @deprecated JSDoc tag.

The backwards compatibility export is thoughtful, but the deprecation notice is only in a comment. Adding a formal @deprecated JSDoc tag would show warnings in users' IDEs, making the deprecation more visible.

🔎 Proposed enhancement
-// Legacy exports for backwards compatibility (deprecated)
-export { create as init } from "./api";
+/**
+ * @deprecated Use `create` instead. This export will be removed in a future version.
+ */
+export { create as init } from "./api";
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ffee16a and 2583611.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (68)
  • .github/workflows/pr-preview-push.yaml
  • .github/workflows/pr-preview.yaml
  • .github/workflows/release.yaml
  • apps/cli/bin/create-better-t-stack
  • apps/cli/package.json
  • apps/cli/scripts/build.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/api.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/index.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/prompts/api.ts
  • apps/cli/src/prompts/auth.ts
  • apps/cli/src/prompts/backend.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/src/prompts/database-setup.ts
  • apps/cli/src/prompts/database.ts
  • apps/cli/src/prompts/examples.ts
  • apps/cli/src/prompts/frontend.ts
  • apps/cli/src/prompts/git.ts
  • apps/cli/src/prompts/install.ts
  • apps/cli/src/prompts/orm.ts
  • apps/cli/src/prompts/package-manager.ts
  • apps/cli/src/prompts/payments.ts
  • apps/cli/src/prompts/project-name.ts
  • apps/cli/src/prompts/runtime.ts
  • apps/cli/src/prompts/server-deploy.ts
  • apps/cli/src/prompts/web-deploy.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/utils/errors.ts
  • apps/cli/src/utils/file-formatter.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/render-title.ts
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/tsconfig.json
  • apps/cli/tsdown.config.ts
  • opentui
💤 Files with no reviewable changes (21)
  • apps/cli/src/prompts/payments.ts
  • apps/cli/src/prompts/api.ts
  • apps/cli/src/prompts/runtime.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/prompts/database.ts
  • apps/cli/src/utils/render-title.ts
  • apps/cli/src/prompts/web-deploy.ts
  • apps/cli/src/prompts/examples.ts
  • apps/cli/src/prompts/orm.ts
  • apps/cli/src/prompts/project-name.ts
  • apps/cli/tsdown.config.ts
  • apps/cli/src/prompts/install.ts
  • apps/cli/src/prompts/database-setup.ts
  • apps/cli/src/prompts/server-deploy.ts
  • apps/cli/src/prompts/frontend.ts
  • apps/cli/src/prompts/git.ts
  • apps/cli/src/prompts/backend.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/src/prompts/package-manager.ts
  • apps/cli/src/prompts/auth.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • apps/cli/src/helpers/addons/addons-setup.ts
  • opentui
  • apps/cli/src/helpers/core/convex-codegen.ts
  • apps/cli/src/tui/use-logger.ts
  • apps/cli/src/utils/docker-utils.ts
  • apps/cli/src/cli.ts
  • apps/cli/src/helpers/core/create-project.ts
  • .github/workflows/pr-preview-push.yaml
  • apps/cli/src/helpers/core/db-setup.ts
  • apps/cli/src/helpers/addons/starlight-setup.ts
  • apps/cli/src/helpers/database-providers/mongodb-atlas-setup.ts
  • apps/cli/src/helpers/core/add-deployment.ts
  • apps/cli/tsconfig.json
  • apps/cli/src/api.ts
  • apps/cli/src/helpers/addons/tui-setup.ts
  • apps/cli/bin/create-better-t-stack
  • apps/cli/src/utils/sponsors.ts
  • apps/cli/src/helpers/core/install-dependencies.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/errors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/index.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/errors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/index.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/errors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/index.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/errors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/index.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/utils/project-directory.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/utils/errors.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/utils/logger.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/database-providers/turso-setup.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/index.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/utils/command-exists.ts
  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/tui/app.tsx
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/src/helpers/addons/ruler-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/utils/open-url.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/helpers/addons/wxt-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
  • apps/cli/src/utils/file-formatter.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Prefer `Bun.file` over `node:fs` readFile/writeFile methods

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/helpers/database-providers/neon-setup.ts
  • apps/cli/src/helpers/addons/fumadocs-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/src/utils/file-formatter.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Applied to files:

  • apps/cli/src/helpers/addons/oxlint-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
  • apps/cli/src/helpers/core/project-config.ts
  • apps/cli/scripts/publish.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.sql` for Postgres instead of `pg` or `postgres.js`

Applied to files:

  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/database-providers/prisma-postgres-setup.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` module for SQLite instead of `better-sqlite3`

Applied to files:

  • apps/cli/src/helpers/database-providers/supabase-setup.ts
  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/scripts/build.ts
  • apps/cli/package.json
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, when passing the Ultracite CLI --integrations flag, supply git hooks as a single space-separated string (e.g., gitHooks.join(" ")) rather than spreading the array like other Ultracite flags. This has been tested and confirmed to work. Ensure the code uses a single string created by joining the gitHooks array with spaces for the --integrations argument.

Applied to files:

  • apps/cli/src/helpers/addons/ultracite-setup.ts
📚 Learning: 2025-12-18T19:15:48.478Z
Learnt from: therealsamyak
Repo: AmanVarshney01/create-better-t-stack PR: 711
File: apps/cli/src/helpers/addons/ultracite-setup.ts:200-205
Timestamp: 2025-12-18T19:15:48.478Z
Learning: In apps/cli/src/helpers/addons/ultracite-setup.ts, the Ultracite CLI's `--integrations` flag requires git hooks to be passed as a single space-separated string (e.g., `gitHooks.join(" ")`) rather than using the spread operator like other Ultracite flags. This has been tested and confirmed to work.

Applied to files:

  • apps/cli/src/tui/app.tsx
  • apps/cli/src/helpers/core/git.ts
  • apps/cli/scripts/publish.ts
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Always add 'use node'; to the top of files containing actions that use Node.js built-in modules

Applied to files:

  • apps/cli/src/tui/app.tsx
  • apps/cli/package.json
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript type aliases instead of interface declarations

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{ts,tsx} : Do not use explicit return types

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Be strict with types, particularly around id's of documents; if a function takes in an id for a document in the 'users' table, take in Id<'users'> rather than string

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : Always use as const for string literals in discriminated union types

Applied to files:

  • apps/cli/src/tui/app.tsx
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.serve()` which supports WebSockets, HTTPS, and routes instead of `express`

Applied to files:

  • apps/cli/src/helpers/addons/tauri-setup.ts
  • apps/cli/src/constants.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Run server with `bun --hot <file>` to enable hot reloading during development

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.redis` for Redis instead of `ioredis`

Applied to files:

  • apps/cli/package.json
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to package.json : Always add types/node to your package.json when using any Node.js built-in modules

Applied to files:

  • apps/cli/package.json
🧬 Code graph analysis (10)
apps/cli/src/helpers/addons/oxlint-setup.ts (2)
apps/cli/src/utils/logger.ts (1)
  • log (90-96)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/utils/project-directory.ts (1)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/get-latest-cli-version.ts (1)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (84-84)
apps/cli/src/helpers/database-providers/neon-setup.ts (5)
apps/cli/src/index.ts (2)
  • PackageManager (39-39)
  • ProjectConfig (41-41)
apps/cli/test/test-utils.ts (1)
  • PackageManager (171-171)
apps/cli/src/types.ts (2)
  • PackageManager (54-54)
  • ProjectConfig (67-67)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/addons/fumadocs-setup.ts (3)
apps/cli/src/types.ts (2)
  • TEMPLATE_VALUES (43-43)
  • ProjectConfig (67-67)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/test/test-utils.ts (2)
apps/cli/src/api.ts (3)
  • CreateResult (70-85)
  • CreateOptions (31-68)
  • create (108-201)
apps/cli/src/index.ts (4)
  • CreateResult (26-26)
  • CreateOptions (26-26)
  • create (26-26)
  • create (51-51)
apps/cli/src/helpers/addons/wxt-setup.ts (2)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/src/helpers/database-providers/turso-setup.ts (2)
apps/cli/src/utils/command-exists.ts (1)
  • commandExists (3-16)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/helpers/addons/ruler-setup.ts (3)
apps/cli/src/index.ts (1)
  • ProjectConfig (41-41)
apps/cli/src/utils/logger.ts (2)
  • log (90-96)
  • error (63-65)
apps/cli/src/utils/package-runner.ts (1)
  • getPackageExecutionCommand (11-23)
apps/cli/scripts/publish.ts (1)
apps/cli/scripts/build.ts (2)
  • version (166-166)
  • builtPackages (166-166)
🪛 GitHub Actions: Test
apps/cli/test/test-utils.ts

[error] 149-151: Test assertion failed: expect(result.success).toBe(false) but received true in expectError helper.

Comment on lines +17 to 24
export function exitWithError(message: string): never {
consola.error(message);
throw new CLIError(message);
}

export function exitCancelled(message = "Operation cancelled"): never {
cancel(pc.red(message));
if (isProgrammatic()) {
throw new Error(message);
}
process.exit(0);
throw new CancelledError(message);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all usages of exitWithError and exitCancelled across the codebase

echo "=== Files in repository ==="
git ls-files | grep -E "\.(ts|tsx|js|jsx)$" | head -20

echo ""
echo "=== Usages of exitWithError ==="
rg -nP --type=ts '\bexitWithError\s*\(' -B2 -A2

echo ""
echo "=== Usages of exitCancelled ==="
rg -nP --type=ts '\bexitCancelled\s*\(' -B2 -A2

Repository: AmanVarshney01/create-better-t-stack

Length of output: 30960


🏁 Script executed:

#!/bin/bash
# Check the actual implementation and context of the error utilities file

echo "=== Full errors.ts file ==="
cat apps/cli/src/utils/errors.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 878


🏁 Script executed:

#!/bin/bash
# Search for imports of these functions to understand usage patterns

echo "=== Imports of exitWithError and exitCancelled ==="
rg -nP --type=ts "from.*errors|import.*exitWithError|import.*exitCancelled" -B1 -A1

Repository: AmanVarshney01/create-better-t-stack

Length of output: 2262


🏁 Script executed:

#!/bin/bash
# Find the main CLI entry point and check error handling

echo "=== Looking for main CLI entry ==="
cat apps/cli/src/cli.ts | head -100

echo ""
echo "=== Search for exitCancelled with broader context ==="
rg -nP 'exitCancelled' --type=ts -B3 -A3

echo ""
echo "=== Check for any error handlers or try-catch at top level ==="
rg -nP 'catch.*error|process.exit|handleError|error handling' apps/cli/src/cli.ts -B2 -A2

Repository: AmanVarshney01/create-better-t-stack

Length of output: 5020


🏁 Script executed:

#!/bin/bash
# Check if this is truly a function declaration (not arrow function) based on coding guidelines

echo "=== Check function declaration style in errors.ts ==="
cat apps/cli/src/utils/errors.ts

echo ""
echo "=== Verify all functions use standard declaration syntax ==="
rg -nP 'export (function|const.*=)' apps/cli/src/utils/errors.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 1182


Remove explicit return type annotations per TypeScript coding guidelines.

The functions exitWithError, exitCancelled, and handleError have explicit : never return type annotations. Per the coding guidelines for TypeScript files, explicit return types should not be used. Remove these annotations:

export function exitWithError(message: string) {
  consola.error(message);
  throw new CLIError(message);
}

export function exitCancelled(message = "Operation cancelled") {
  throw new CancelledError(message);
}

export function handleError(error: unknown, fallbackMessage?: string) {
  const message = error instanceof Error ? error.message : fallbackMessage || String(error);
  consola.error(message);
  throw new CLIError(message);
}

Also note that exitCancelled appears unused throughout the codebase and should be removed if no longer needed.

🤖 Prompt for AI Agents
In apps/cli/src/utils/errors.ts around lines 17 to 24, remove the explicit ":
never" return type annotations from exitWithError and exitCancelled (and also
remove the annotation from handleError if present) so the functions use implicit
return types; update exitWithError to be declared as export function
exitWithError(message: string) { ... }, exitCancelled as export function
exitCancelled(message = "Operation cancelled") { ... }, and handleError as
export function handleError(error: unknown, fallbackMessage?: string) { ... };
additionally, check the codebase for references to exitCancelled and delete the
function from this file if it is unused.

Comment on lines +7 to +10
export async function formatFile(_filePath: string, content: string): Promise<string | null> {
// Return content unchanged - formatting removed for bun compile compatibility
// Users should run their preferred formatter (biome, prettier, etc.) after project creation
return content;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, read the actual file to confirm the current state
cat -n apps/cli/src/utils/file-formatter.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 680


🏁 Script executed:

# Search for all imports and usages of formatFile in the codebase
rg -n --type=ts --type=tsx 'formatFile' -B2 -A2

Repository: AmanVarshney01/create-better-t-stack

Length of output: 107


🏁 Script executed:

# Also check if there are any JavaScript/JSX files that might import it
rg -n 'formatFile' --type=js --type=jsx -B2 -A2

Repository: AmanVarshney01/create-better-t-stack

Length of output: 107


🏁 Script executed:

# Search for formatFile without type restrictions
rg -n 'formatFile' -B2 -A2

Repository: AmanVarshney01/create-better-t-stack

Length of output: 1329


🏁 Script executed:

# Also check for any imports of this function
rg -n 'from.*file-formatter|import.*formatFile' -B1 -A1

Repository: AmanVarshney01/create-better-t-stack

Length of output: 303


🏁 Script executed:

# Check the entire apps/cli/src directory structure to understand the codebase
fd -t f '\.ts$|\.js$' apps/cli/src/ | head -20

Repository: AmanVarshney01/create-better-t-stack

Length of output: 883


🏁 Script executed:

# Read the template-processor.ts file around the formatFile call
sed -n '25,45p' apps/cli/src/utils/template-processor.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 735


🏁 Script executed:

# Also read more context to understand what happens with formattedContent
sed -n '30,50p' apps/cli/src/utils/template-processor.ts

Repository: AmanVarshney01/create-better-t-stack

Length of output: 657


Remove explicit return type and simplify to synchronous function.

This function has several fixable issues:

  1. Coding guideline violation: Line 7 uses explicit return type : Promise<string | null>, but TypeScript files should not use explicit return types per the coding guidelines.

  2. Unnecessary async wrapper: The function is declared async but performs no asynchronous operations. Remove async and return Promise wrapper.

  3. Return type inconsistency: The signature declares | null but always returns content (a string), making the null check in the caller dead code.

Suggested fix:

-export async function formatFile(_filePath: string, content: string): Promise<string | null> {
+export function formatFile(_filePath: string, content: string) {
   // Return content unchanged - formatting removed for bun compile compatibility
   // Users should run their preferred formatter (biome, prettier, etc.) after project creation
   return content;
 }

The caller in template-processor.ts (line 35) will still work correctly since any string is truthy.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function formatFile(_filePath: string, content: string): Promise<string | null> {
// Return content unchanged - formatting removed for bun compile compatibility
// Users should run their preferred formatter (biome, prettier, etc.) after project creation
return content;
export function formatFile(_filePath: string, content: string) {
// Return content unchanged - formatting removed for bun compile compatibility
// Users should run their preferred formatter (biome, prettier, etc.) after project creation
return content;
}
🤖 Prompt for AI Agents
In apps/cli/src/utils/file-formatter.ts around lines 7 to 10, the function is
declared async with an explicit Promise<string | null> return type and returns a
string constant, which violates the type/async guidelines and makes the null
union dead code; change the function to a synchronous one that returns a plain
string (remove async and the explicit Promise<string | null> return type and the
null union) so it simply returns content as a string.

Comment on lines +10 to +15
export interface LogEntry {
id: number;
level: LogLevel;
message: string;
timestamp: Date;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Convert interface to type alias.

The coding guidelines specify using TypeScript type aliases instead of interface declarations.

🔎 Proposed fix
-export interface LogEntry {
+export type LogEntry = {
   id: number;
   level: LogLevel;
   message: string;
   timestamp: Date;
-}
+};

As per coding guidelines.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface LogEntry {
id: number;
level: LogLevel;
message: string;
timestamp: Date;
}
export type LogEntry = {
id: number;
level: LogLevel;
message: string;
timestamp: Date;
};
🤖 Prompt for AI Agents
In apps/cli/src/utils/logger.ts around lines 10 to 15, the LogEntry is declared
as a TypeScript interface but the project guideline requires using a type alias;
replace the interface declaration with an exported type alias named LogEntry
that has the same properties (id: number, level: LogLevel, message: string,
timestamp: Date) and ensure the export and member types remain unchanged.

Comment on lines +53 to 59
case "rename": {
if (!options.newPath) {
throw new Error("New path must be provided when action is 'rename'");
}
case "cancel":
return exitCancelled("Operation cancelled.");
log.info(`Using alternative path: ${options.newPath}`);
return await handleDirectoryConflict(options.newPath, silent);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Recursive call may lose user-specified options.

When action is "rename", the recursive call at line 58 doesn't forward the options parameter:

return await handleDirectoryConflict(options.newPath, silent);

If the renamed path also conflicts, the default action: "overwrite" will be used instead of preserving the user's original intent.

🔎 Proposed fix
     case "rename": {
       if (!options.newPath) {
         throw new Error("New path must be provided when action is 'rename'");
       }
       log.info(`Using alternative path: ${options.newPath}`);
-      return await handleDirectoryConflict(options.newPath, silent);
+      return await handleDirectoryConflict(options.newPath, silent, {
+        ...options,
+        newPath: undefined, // Prevent infinite recursion
+      });
     }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/cli/src/helpers/addons/tui-setup.ts (1)

29-34: Re-throw errors to allow caller error handling.

The error is logged but not re-thrown, which prevents callers from detecting and handling setup failures. This could lead to silent failures in the setup pipeline.

🔎 Proposed fix
   } catch (error) {
     log.error("Failed to set up OpenTUI");
     if (error instanceof Error) {
       console.error(pc.red(error.message));
     }
+    throw error;
   }
 }
apps/cli/test/test-utils.ts (1)

149-154: Add configuration validation to the create() API before calling createProject().

The create() function builds a configuration but never validates it, allowing invalid combinations (e.g., drizzle + mongodb) to pass through successfully. This causes tests using expectError() to fail—they expect result.success to be false, but the API returns success: true for invalid configs. Import and call validateConfigForProgrammaticUse(config) from ./utils/config-validation immediately before createProject(config) so that validation errors are caught and returned with success: false.

Also, convert TestConfig and TestResult from interface to type declarations per the TypeScript coding guidelines (lines 63 and 71).

♻️ Duplicate comments (16)
apps/cli/src/utils/file-formatter.ts (1)

7-10: Remove explicit return type and simplify to synchronous function.

The previous review comment's concerns remain unaddressed:

  1. Explicit return type violation: Line 7 declares : Promise<string | null>, but per coding guidelines, TypeScript files should not use explicit return types.

  2. Unnecessary async: The function is declared async but contains no asynchronous operations—it immediately returns the input.

  3. Dead code in return type: The | null union is never used; the function always returns content (a string).

🔎 Proposed fix
-export async function formatFile(_filePath: string, content: string): Promise<string | null> {
+export function formatFile(_filePath: string, content: string) {
   // Return content unchanged - formatting removed for bun compile compatibility
   // Users should run their preferred formatter (biome, prettier, etc.) after project creation
   return content;
 }

Based on coding guidelines, TypeScript files should not use explicit return types.

apps/cli/src/helpers/core/git.ts (1)

20-21: Add error handling for git add and commit operations.

These commands use .quiet() but not .nothrow(), which means they will throw unhandled errors if they fail (e.g., missing git config, permissions issues). This is inconsistent with the explicit error handling pattern established for git init on lines 14-18.

🔎 Suggested fix with consistent error handling
- await $`git add -A`.cwd(projectDir).quiet();
- await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet();
+ const addResult = await $`git add -A`.cwd(projectDir).nothrow().quiet();
+ if (addResult.exitCode !== 0) {
+   throw new Error(`Git add failed: ${addResult.stderr.toString()}`);
+ }
+ 
+ const commitResult = await $`git commit -m "initial commit"`.cwd(projectDir).nothrow().quiet();
+ if (commitResult.exitCode !== 0) {
+   throw new Error(`Git commit failed: ${commitResult.stderr.toString()}`);
+ }
apps/cli/src/utils/project-directory.ts (1)

53-59: Recursive call still doesn't forward options.

This is the same issue flagged in the previous review. When action is "rename", the recursive call at line 58 doesn't forward the options parameter:

return await handleDirectoryConflict(options.newPath, silent);

If the renamed path also conflicts, the default action: "overwrite" will be used instead of preserving the user's original intent or allowing for consistent conflict resolution behavior.

🔎 Proposed fix
     case "rename": {
       if (!options.newPath) {
         throw new Error("New path must be provided when action is 'rename'");
       }
       log.info(`Using alternative path: ${options.newPath}`);
-      return await handleDirectoryConflict(options.newPath, silent);
+      return await handleDirectoryConflict(options.newPath, silent, {
+        ...options,
+        newPath: undefined, // Prevent infinite recursion
+      });
     }
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

52-56: Security concern: Executing downloaded script without verification.

This downloads and executes a script from the internet without verification. This was already flagged in a previous review.

apps/cli/src/utils/errors.ts (1)

17-17: Remove explicit return type annotations per TypeScript coding guidelines.

The functions exitWithError, exitCancelled, and handleError have explicit : never return type annotations. Per the coding guidelines for TypeScript files, explicit return types should not be used.

As per coding guidelines, TypeScript files should not use explicit return types.

Also applies to: 22-22, 26-26

apps/cli/scripts/publish.ts (2)

21-24: Potential undefined value when --tag is the last argument.

If --tag is provided as the last argument without a value, process.argv[indexOf + 1] will be undefined, and tag becomes undefined rather than defaulting to "latest".

🔎 Proposed fix
 const dryRun = process.argv.includes("--dry-run");
-const tag = process.argv.includes("--tag")
-  ? process.argv[process.argv.indexOf("--tag") + 1]
-  : "latest";
+const tagIndex = process.argv.indexOf("--tag");
+const tag = tagIndex !== -1 && process.argv[tagIndex + 1] && !process.argv[tagIndex + 1].startsWith("--")
+  ? process.argv[tagIndex + 1]
+  : "latest";

96-103: Merge instead of replacing optionalDependencies to preserve existing packages.

The assignment at line 101 replaces all existing optionalDependencies. If package.json contains other optional dependencies (e.g., @opentui/core-* platform packages), they will be deleted.

🔎 Proposed fix
-pkg.optionalDependencies = optionalDeps;
+pkg.optionalDependencies = {
+  ...(pkg.optionalDependencies || {}),
+  ...optionalDeps,
+};
apps/cli/src/api.ts (1)

134-161: Redundant ternary expressions in config fallback logic.

The ternary expressions like options.X ?? (options.defaults ? defaultConfig.X : defaultConfig.X) are redundant since both branches return defaultConfig.X. Simplify to options.X ?? defaultConfig.X.

🔎 Proposed fix
-      frontend:
-        options.frontend ?? (options.defaults ? defaultConfig.frontend : defaultConfig.frontend),
+      frontend: options.frontend ?? defaultConfig.frontend,

Apply this pattern to all similar lines (backend, runtime, database, orm, auth, payments, api, addons, examples, dbSetup, webDeploy, serverDeploy, git, packageManager).

apps/cli/package.json (3)

73-74: Version mismatch between @opentui/core and platform-specific packages.

The main dependency uses "@opentui/core": "^0.1.62" but the optional platform bindings pin to 0.1.63. This mismatch could cause resolution conflicts.

Also applies to: 101-106


42-54: Publishing TypeScript source files may break non-Bun consumers.

The package points main, types, and exports to TypeScript source files (./src/index.ts). This will fail for consumers who don't use Bun or a similar runtime that can execute TypeScript directly.


68-68: Removed build safety guardrail from prepublishOnly.

The prepublishOnly script only echoes a message instead of validating that required artifacts exist, increasing risk of publishing incomplete packages.

apps/cli/src/tui/app.tsx (3)

158-161: Use path.join instead of string concatenation for paths.

String concatenation with / won't work correctly on Windows. Use path.join for cross-platform compatibility.

🔎 Proposed fix
+import path from "node:path";
+
 // In the useEffect:
 const fullConfig: ProjectConfig = {
   projectName: config.projectName || defaultConfig.projectName,
-  projectDir: process.cwd() + "/" + (config.projectName || defaultConfig.projectName),
+  projectDir: path.join(process.cwd(), config.projectName || defaultConfig.projectName),
   relativePath: config.projectName || defaultConfig.projectName,

253-264: Use path.join for projectDir path construction.

Same issue as above - string concatenation with / should be replaced with path.join for Windows compatibility.

🔎 Proposed fix
 {currentStep.type === "input" && (
   <InputPrompt
     onSubmit={(v) => {
       updateConfig(currentStep.id, v);
       if (currentStep.id === "projectName") {
-        updateConfig("projectDir", process.cwd() + "/" + v);
+        updateConfig("projectDir", path.join(process.cwd(), v));
         updateConfig("relativePath", v);
       }
       goNext();
     }}
     onBack={stepIndex > 0 ? goPrev : undefined}
   />
 )}

31-35: Convert interface to type alias.

Per coding guidelines, use TypeScript type aliases instead of interface declarations.

🔎 Proposed fix
-export interface TuiOptions {
+export type TuiOptions = {
   initialConfig?: Partial<ProjectConfig>;
   onComplete: (config: ProjectConfig) => Promise<void>;
   onCancel: () => void;
-}
+};
.github/workflows/pr-preview.yaml (1)

104-117: Add error handling to fail on first publish error.

The loop continues even if a platform package fails to publish. Without set -e, some platform packages could fail silently.

🔎 Proposed fix
      - name: Publish CLI platform packages to NPM
        run: |
+         set -e
          cd apps/cli/dist
          ls -la
          for dir in */; do
            if [ -f "$dir/package.json" ]; then
              echo "Publishing $dir..."
              cd "$dir"
              bun publish --access public --tag ${{ steps.version.outputs.tag }}
              cd ..
            fi
          done
        env:
          NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}

Note: The working directory concern from the past review is not actually an issue since GitHub Actions steps always start from the repository root. However, the error handling is still needed.

apps/cli/src/helpers/addons/ruler-setup.ts (1)

9-35: Remove unsupported agent "crush" from RulerAgent type.

Per the past review, "crush" is not a supported agent in the @intellectronica/ruler library. The remaining agents are all verified as supported.

🔎 Proposed fix
 type RulerAgent =
   | "amp"
   | "copilot"
   | "claude"
   | "codex"
   | "cursor"
   | "windsurf"
   | "cline"
   | "aider"
   | "firebase"
   | "gemini-cli"
   | "junie"
   | "kilocode"
   | "opencode"
-  | "crush"
   | "zed"
   | "qwen"
   | "amazonqcli"
   | "augmentcode"
   | "firebender"
   | "goose"
   | "jules"
   | "kiro"
   | "openhands"
   | "roo"
   | "trae"
   | "warp";
🧹 Nitpick comments (25)
apps/cli/src/helpers/addons/fumadocs-setup.ts (2)

4-4: Unused import: picocolors.

The pc import from picocolors is not used in this file. Consider removing it to reduce unnecessary dependencies.

🔎 Proposed fix
 import path from "node:path";
 import { $ } from "bun";
 import fs from "fs-extra";
-import pc from "picocolors";
 import type { ProjectConfig } from "../../types";

61-66: Consider propagating errors to the caller.

The error is caught and logged but not re-thrown or otherwise indicated to the caller. This means the calling code cannot determine if Fumadocs setup succeeded or failed, potentially leading to silent failures in the overall setup flow.

🔎 Proposed fix to re-throw after logging
   } catch (error) {
     log.error("Failed to set up Fumadocs");
     if (error instanceof Error) {
       log.error(error.message);
     }
+    throw error;
   }

Alternatively, return a boolean or result object to indicate success/failure if throwing is not desired.

apps/cli/src/constants.ts (1)

46-82: Consider adding fallback logging or failing explicitly when in compiled binary mode.

When isCompiledBinary() returns true but none of the fallback paths (lines 49-75) succeed, the code silently falls through to the standard JS mode path resolution (lines 79-81). This could lead to confusing runtime errors later when templates aren't found at the expected location.

Consider either:

  1. Throwing an error if all compiled binary paths fail
  2. Adding debug logging to indicate which fallback was used
🔎 Option 1: Fail explicitly in compiled binary mode
     const simpleTemplatesPath = path.resolve(binaryDir, "..", "templates");
     if (fs.existsSync(simpleTemplatesPath)) {
       return path.resolve(binaryDir, "..");
     }
+
+    throw new Error(
+      `Unable to locate templates directory for compiled binary. ` +
+      `Searched from: ${binaryDir}`
+    );
   }
 
   // Standard JS mode - relative to this file in dist/
apps/cli/src/helpers/addons/tui-setup.ts (1)

11-11: Add runtime validation for the template parameter.

While TypeScript provides compile-time type safety, the template parameter should be validated at runtime to catch invalid values passed dynamically or from external sources.

🔎 Proposed validation
+const validTemplates: TuiTemplate[] = ["core", "react", "solid"];
+
 export async function setupTui(config: ProjectConfig, template: TuiTemplate = "react") {
   const { packageManager, projectDir } = config;
+
+  if (!validTemplates.includes(template)) {
+    throw new Error(`Invalid TUI template: ${template}. Valid options are: ${validTemplates.join(", ")}`);
+  }
 
   try {
apps/cli/src/helpers/addons/ultracite-setup.ts (1)

38-61: Remove explicit return type.

The function includes an explicit return type (: string[]), which violates the TypeScript coding guideline: "Do not use explicit return types."

Proposed change
-function getFrameworksFromFrontend(frontend: string[]): string[] {
+function getFrameworksFromFrontend(frontend: string[]) {
apps/cli/src/helpers/database-providers/neon-setup.ts (1)

34-37: Fragile string transformation for success message.

The string replacement logic stepText.replace("...", "").replace("ing ", "ed ") is brittle and may not work correctly for all step texts (e.g., "Running..." would become "Runed" instead of "Ran"). Consider either using distinct step/success messages or a more robust transformation.

🔎 Suggested improvement
 async function executeNeonCommand(
   packageManager: PackageManager,
   commandArgsString: string,
-  stepText?: string,
+  options?: { stepText?: string; successText?: string },
 ) {
   try {
     const fullCommand = getPackageExecutionCommand(packageManager, commandArgsString);
 
-    if (stepText) log.step(stepText);
+    if (options?.stepText) log.step(options.stepText);
     const result = await $`${{ raw: fullCommand }}`.text();
-    if (stepText) log.success(stepText.replace("...", "").replace("ing ", "ed ").trim());
+    if (options?.successText) log.success(options.successText);
+    else if (options?.stepText) log.success("Done");
     return { stdout: result };
   } catch (error) {
-    log.error(`Failed: ${stepText || "Command execution"}`);
+    log.error(`Failed: ${options?.stepText || "Command execution"}`);
     throw error;
   }
 }
apps/cli/src/helpers/core/db-setup.ts (1)

184-188: Inconsistent error logging with other setup files.

This file uses consola.error(pc.red(...)) while the individual provider files have migrated to the centralized log.error(). Consider updating for consistency across the codebase.

🔎 Suggested fix
+import { log } from "../../utils/logger";
 // ... at the top of the file

   } catch (error) {
     if (error instanceof Error) {
-      consola.error(pc.red(error.message));
+      log.error(error.message);
     }
   }
apps/cli/src/helpers/database-providers/turso-setup.ts (1)

258-265: Inconsistent error logging - uses consola instead of log.

For consistency with the rest of the file and other setup modules, consider using log.error instead of consola.error.

🔎 Suggested fix
   } catch (error) {
-    consola.error(
-      pc.red(`Error during Turso setup: ${error instanceof Error ? error.message : String(error)}`),
-    );
+    log.error(
+      `Error during Turso setup: ${error instanceof Error ? error.message : String(error)}`,
+    );
     await writeEnvFile(projectDir, backend);
     displayManualSetupInstructions();
     log.info("Setup completed with manual configuration required.");
   }
apps/cli/src/tui/components/spinner.tsx (1)

4-13: Consider moving frames array outside the component.

The frames array is recreated on every render. Moving it outside the component definition would avoid this unnecessary allocation.

🔎 Proposed refactor
+const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
+
 export function Spinner(props: { text: string }) {
-  const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
   const [frame, setFrame] = useState(0);

   useEffect(() => {
     const interval = setInterval(() => {
-      setFrame((f: number) => (f + 1) % frames.length);
+      setFrame((f: number) => (f + 1) % SPINNER_FRAMES.length);
     }, 80);
     return () => clearInterval(interval);
   }, []);

   return (
     <text>
-      <span fg={theme.primary}>{frames[frame]}</span>
+      <span fg={theme.primary}>{SPINNER_FRAMES[frame]}</span>
       <span fg={theme.text}> {props.text}</span>
     </text>
   );
 }
apps/cli/scripts/build.ts (1)

69-77: Consider logging the actual error when platform binary installation fails.

The warning message at line 75 doesn't include the actual error details, which could make troubleshooting difficult when cross-compilation fails.

🔎 Proposed improvement
   try {
     await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`.quiet();
   } catch (e) {
-    console.warn("Warning: Could not install all platform binaries, some builds may fail\n");
+    console.warn("Warning: Could not install all platform binaries, some builds may fail");
+    console.warn(`Error: ${e instanceof Error ? e.message : String(e)}\n`);
   }
apps/cli/src/api.ts (2)

31-68: Consider using type aliases instead of interfaces per coding guidelines.

The coding guidelines specify using TypeScript type aliases instead of interface declarations. Both CreateOptions and CreateResult use interface.

🔎 Proposed refactor
-export interface CreateOptions {
+export type CreateOptions = {
   /** Project name or path */
   projectName?: string;
   // ... rest of properties
-}
+};

-export interface CreateResult {
+export type CreateResult = {
   /** Whether the project was created successfully */
   success: boolean;
   // ... rest of properties
-}
+};

203-203: Remove vestigial comment.

Line 203 has an incomplete/unnecessary comment that doesn't add value.

🔎 Proposed fix
-// Types are exported above via the main export
apps/cli/bin/create-better-t-stack (2)

22-32: Consider using standard function declaration syntax.

Per coding guidelines, functions should use standard function declarations. The run function is defined correctly, but the fallback on line 30 when result.status is not a number defaults to exit code 0, which may mask failures.

🔎 Proposed fix for exit code handling
-    const code = typeof result.status === "number" ? result.status : 0;
+    const code = typeof result.status === "number" ? result.status : 1;

A non-numeric status typically indicates an abnormal termination, so defaulting to 1 (failure) is safer than 0 (success).


34-38: Environment variable override has no path validation.

The CREATE_BETTER_T_STACK_BIN_PATH override directly executes whatever path is provided without checking if the file exists. While this is user-controlled, adding an existence check would provide a better error message.

🔎 Proposed improvement
 const envPath = process.env.CREATE_BETTER_T_STACK_BIN_PATH;
 if (envPath) {
+    if (!existsSync(envPath)) {
+        console.error(`Binary not found at CREATE_BETTER_T_STACK_BIN_PATH: ${envPath}`);
+        process.exit(1);
+    }
     run(envPath);
 }
apps/cli/test/test-utils.ts (1)

71-75: Consider using type alias instead of interface per coding guidelines.

Per coding guidelines, TypeScript type aliases should be preferred over interface declarations.

🔎 Proposed refactor
-export interface TestConfig extends CreateOptions {
+export type TestConfig = CreateOptions & {
   projectName?: string;
   expectError?: boolean;
   expectedErrorMessage?: string;
-}
+};
apps/cli/src/tui/components/log-display.tsx (2)

12-13: Inconsistent color source for warn level.

The warn case uses a hardcoded hex color #f59e0b while all other cases use theme.* constants. Consider adding a warn or warning property to the theme for consistency.

🔎 Proposed fix

Either add to theme.ts:

export const theme = {
  // ... existing colors
  warn: "#f59e0b",
};

Then update log-display.tsx:

     case "warn":
-      return { icon: "⚠", color: "#f59e0b" };
+      return { icon: "⚠", color: theme.warn };

4-17: Missing handler for "step" log level.

The LogEntry["level"] type includes "step" (from logger.ts), but getLogIcon doesn't have a dedicated case for it, falling through to the default. Consider adding explicit handling.

🔎 Proposed addition
     case "warn":
       return { icon: "⚠", color: "#f59e0b" };
+    case "step":
+      return { icon: "→", color: theme.primary };
     default:
       return { icon: "•", color: theme.muted };
apps/cli/src/tui/components/prompts/input.tsx (1)

1-1: Remove unused useState import.

The useState hook is imported but never used in this component.

🔎 Proposed fix
-import { useState } from "react";
 import { useKeyboard } from "@opentui/react";
apps/cli/src/tui/components/prompts/select.tsx (1)

20-26: Consider guarding against empty options array.

If props.options is empty, pressing return on line 24 would cause a runtime error when accessing props.options[i].value. While this may be unlikely in practice, a defensive check would prevent potential crashes.

🔎 Proposed fix
  useKeyboard((key) => {
    if (key.name === "up" || key.name === "k") setI((x: number) => Math.max(0, x - 1));
    else if (key.name === "down" || key.name === "j")
      setI((x: number) => Math.min(props.options.length - 1, x + 1));
-   else if (key.name === "return") props.onSelect(props.options[i].value);
+   else if (key.name === "return" && props.options.length > 0) props.onSelect(props.options[i].value);
    else if (key.name === "escape" && props.onBack) props.onBack();
  });
apps/cli/src/tui/components/status-bar.tsx (2)

5-6: Hardcoded VERSION contradicts the comment.

The comment states "Version from package.json" but the value is hardcoded. This will drift out of sync with the actual package version. Consider importing the version dynamically or updating the comment to reflect the manual maintenance requirement.

🔎 Proposed fix - dynamic import
-// Version from package.json
-const VERSION = "3.11.0";
+import packageJson from "../../../package.json";
+
+const VERSION = packageJson.version;

Note: This assumes your bundler/runtime supports JSON imports. With Bun, this should work out of the box.


9-43: Consider using standard function declaration for keybinds.

Per coding guidelines, functions should use standard function declaration syntax instead of arrow functions.

🔎 Proposed fix
 export function StatusBar(props: { phase: Phase; canGoBack: boolean }) {
-  const keybinds = () => {
+  function keybinds() {
     switch (props.phase) {
       // ... cases unchanged
     }
-  };
+  }
apps/cli/src/tui/components/prompts/multi-select.tsx (1)

14-23: Same empty options guard applies here.

Similar to SelectPrompt, if props.options is empty, the space key handler on line 19 would throw when accessing props.options[i].value.

🔎 Proposed fix
  useKeyboard((key) => {
    if (key.name === "up" || key.name === "k") setI((x: number) => Math.max(0, x - 1));
    else if (key.name === "down" || key.name === "j")
      setI((x: number) => Math.min(props.options.length - 1, x + 1));
-   else if (key.name === "space") {
+   else if (key.name === "space" && props.options.length > 0) {
      const v = props.options[i].value;
      setSel((s: string[]) => (s.includes(v) ? s.filter((x: string) => x !== v) : [...s, v]));
    } else if (key.name === "return") props.onSubmit(sel);
.github/workflows/release.yaml (1)

167-183: Binary upload step looks good, but consider adding error handling.

The logic correctly creates tar.gz for Linux and zip for other platforms. However, this step could benefit from set -e to fail fast if any archive creation or upload fails.

🔎 Proposed fix
      - name: Upload binaries to GitHub Release
        if: steps.check-version.outputs.exists == 'false'
        run: |
+         set -e
          VERSION="${{ steps.version.outputs.version }}"
          cd apps/cli/dist
          for dir in better-t-stack-cli-*/; do
apps/cli/src/cli.ts (2)

14-32: Remove unused type imports.

DirectoryConflict and Template are imported but not used in this file. Additionally, path is imported on line 13 but never used.

🔎 Proposed fix
-import path from "node:path";
 import type {
   PackageManager,
   Database,
   ORM,
   Backend,
   Runtime,
   Frontend,
   Addons,
   Examples,
   DatabaseSetup,
   API,
   WebDeploy,
   ServerDeploy,
-  DirectoryConflict,
-  Template,
   Auth,
   Payments,
   ProjectConfig,
 } from "./types";

141-153: Placeholder add command implementation.

The add command has a TODO and just logs a message. Consider either implementing it or hiding it until ready.

🔎 Proposed fix (hide until ready)
-program
-  .command("add")
-  .description("Add addons or deployment configurations to an existing project")
-  .option("--addons <addons...>", "Addons to add")
-  .option("--web-deploy <deploy>", "Web deployment target")
-  .option("--server-deploy <deploy>", "Server deployment target")
-  .option("--project-dir <dir>", "Project directory")
-  .option("--install", "Install dependencies after adding", false)
-  .option("--package-manager <pm>", "Package manager to use")
-  .action(async (options: Record<string, unknown>) => {
-    // TODO: Implement add command with TUI
-    console.log("Add command - TUI coming soon");
-  });
+// TODO: Implement add command with TUI
+// program
+//   .command("add")
+//   .description("Add addons or deployment configurations to an existing project")
+//   ...

Would you like me to help implement the add command or open an issue to track this?

Comment on lines +132 to +146
- name: Publish CLI platform packages to NPM
if: steps.check-version.outputs.exists == 'false'
run: |
cd apps/cli/dist
ls -la
for dir in */; do
if [ -f "$dir/package.json" ]; then
echo "Publishing $dir..."
cd "$dir"
bun publish --access public
cd ..
fi
done
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling to fail on first publish error.

The loop continues even if a platform package fails to publish. Without set -e, the step might succeed despite some platforms failing, leading to incomplete releases.

🔎 Proposed fix
      - name: Publish CLI platform packages to NPM
        if: steps.check-version.outputs.exists == 'false'
        run: |
+         set -e
          cd apps/cli/dist
          ls -la
          for dir in */; do
            if [ -f "$dir/package.json" ]; then
              echo "Publishing $dir..."
              cd "$dir"
              bun publish --access public
              cd ..
            fi
          done
        env:
          NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
🤖 Prompt for AI Agents
In .github/workflows/release.yaml around lines 132 to 146, the publish loop
doesn’t fail on the first npm publish error so the step can succeed despite
partial failures; modify the shell step to stop and fail immediately when any
command fails (e.g., enable strict error handling like set -euo pipefail at the
top of the run block or check the exit status of bun publish and exit non‑zero
on failure) so the workflow fails on the first publish error and prevents
incomplete releases.

Comment on lines +4 to +12
export interface StepConfig {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Convert interface to type alias.

Per coding guidelines, use TypeScript type aliases instead of interface declarations.

🔎 Proposed fix
-export interface StepConfig {
+export type StepConfig = {
   id: string;
   title: string;
   type: "input" | "select" | "multiselect" | "confirm";
   skip?: (config: any) => boolean;
   getDefault?: (config: any) => any;
   getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
   options?: { name: string; value: string; hint?: string }[];
-}
+};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface StepConfig {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
}
export type StepConfig = {
id: string;
title: string;
type: "input" | "select" | "multiselect" | "confirm";
skip?: (config: any) => boolean;
getDefault?: (config: any) => any;
getOptions?: (config: any) => { name: string; value: string; hint?: string }[];
options?: { name: string; value: string; hint?: string }[];
};
🤖 Prompt for AI Agents
In apps/cli/src/tui/steps.ts around lines 4 to 12, the StepConfig is declared as
an interface but must be converted to a TypeScript type alias per guidelines;
replace the "export interface StepConfig { ... }" declaration with an equivalent
"export type StepConfig = { ... }" keeping all property names, types, optional
markers, union literals, and function signatures intact so behavior is
unchanged.

Comment on lines 13 to 27
export const getLatestCLIVersion = (): string => {
// Check if version was embedded at compile time
if (typeof CLI_VERSION !== "undefined") {
return CLI_VERSION;
}

return packageJsonContent.version ?? "1.0.0";
// Fallback to reading package.json (for npm distribution)
try {
const packageJsonPath = path.join(PKG_ROOT, "package.json");
const packageJsonContent = fs.readJSONSync(packageJsonPath);
return packageJsonContent.version ?? "1.0.0";
} catch {
return "1.0.0";
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Refactor to use standard function declaration without explicit return type.

The function uses an arrow function with an explicit return type, which violates two coding guidelines:

  1. Functions should use standard function declaration syntax, not arrow functions
  2. Explicit return types should not be used
🔎 Proposed refactor
-export const getLatestCLIVersion = (): string => {
+export function getLatestCLIVersion() {
   // Check if version was embedded at compile time
   if (typeof CLI_VERSION !== "undefined") {
     return CLI_VERSION;
   }

   // Fallback to reading package.json (for npm distribution)
   try {
     const packageJsonPath = path.join(PKG_ROOT, "package.json");
     const packageJsonContent = fs.readJSONSync(packageJsonPath);
     return packageJsonContent.version ?? "1.0.0";
   } catch {
     return "1.0.0";
   }
-};
+}

As per coding guidelines, use standard function declarations without explicit return types.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getLatestCLIVersion = (): string => {
// Check if version was embedded at compile time
if (typeof CLI_VERSION !== "undefined") {
return CLI_VERSION;
}
return packageJsonContent.version ?? "1.0.0";
// Fallback to reading package.json (for npm distribution)
try {
const packageJsonPath = path.join(PKG_ROOT, "package.json");
const packageJsonContent = fs.readJSONSync(packageJsonPath);
return packageJsonContent.version ?? "1.0.0";
} catch {
return "1.0.0";
}
};
export function getLatestCLIVersion() {
// Check if version was embedded at compile time
if (typeof CLI_VERSION !== "undefined") {
return CLI_VERSION;
}
// Fallback to reading package.json (for npm distribution)
try {
const packageJsonPath = path.join(PKG_ROOT, "package.json");
const packageJsonContent = fs.readJSONSync(packageJsonPath);
return packageJsonContent.version ?? "1.0.0";
} catch {
return "1.0.0";
}
}
🤖 Prompt for AI Agents
In apps/cli/src/utils/get-latest-cli-version.ts around lines 13 to 27, the
exported arrow function with an explicit return type should be converted to a
standard function declaration without an explicit return type; replace the
exported const arrow function with an exported function (export function
getLatestCLIVersion() { ... }) preserving the same logic (check CLI_VERSION,
fallback to reading package.json via path.join(PKG_ROOT, "package.json") and
fs.readJSONSync, return packageJsonContent.version ?? "1.0.0", catch and return
"1.0.0") and keep existing imports and error handling unchanged.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
apps/cli/src/utils/get-latest-cli-version.ts (1)

13-26: Refactor to use standard function declaration without explicit return type.

The function still uses an arrow function with an explicit return type, which violates coding guidelines. This issue was previously flagged and should be addressed.

As per coding guidelines, use standard function declarations without explicit return types.

🧹 Nitpick comments (3)
apps/cli/src/constants.ts (1)

2-2: Consider using Bun.file API instead of node:fs.

The function uses fs.existsSync() from node:fs for path checking. Per coding guidelines, prefer Bun's native APIs over Node.js APIs.

🔎 Proposed refactor using Bun.file
-import fs from "node:fs";
-
 function findPackageRoot(): string {
   const __filename = fileURLToPath(import.meta.url);
   const __dirname = path.dirname(__filename);
 
   const devRoot = path.resolve(__dirname, "..");
   const devTemplatesPath = path.join(devRoot, "templates");
-  if (fs.existsSync(devTemplatesPath)) {
+  if (Bun.file(devTemplatesPath).exists()) {
     return devRoot;
   }
 
   let current = __dirname;
   while (current !== path.dirname(current)) {
     const nodeModulesPath = path.join(current, "node_modules");
-    if (fs.existsSync(nodeModulesPath)) {
+    if (Bun.file(nodeModulesPath).exists()) {
       const mainPackagePath = path.join(nodeModulesPath, "create-better-t-stack");
       const mainTemplatesPath = path.join(mainPackagePath, "templates");
-      if (fs.existsSync(mainTemplatesPath)) {
+      if (Bun.file(mainTemplatesPath).exists()) {
         return mainPackagePath;
       }
     }
 
     const parts = current.split(path.sep);
     const nodeModulesIndex = parts.lastIndexOf("node_modules");
     if (nodeModulesIndex !== -1) {
       const nodeModulesDir = parts.slice(0, nodeModulesIndex + 1).join(path.sep);
       const mainPackagePath = path.join(nodeModulesDir, "create-better-t-stack");
       const mainTemplatesPath = path.join(mainPackagePath, "templates");
-      if (fs.existsSync(mainTemplatesPath)) {
+      if (Bun.file(mainTemplatesPath).exists()) {
         return mainPackagePath;
       }
     }
 
     current = path.dirname(current);
   }
 
   return devRoot;
 }

As per coding guidelines, use Bun's native file APIs.

Also applies to: 15-61

apps/cli/scripts/build.ts (1)

18-18: Consider using Bun.file API for file operations.

The script uses fs from node:fs for directory operations (existsSync, rmSync, mkdirSync). Per coding guidelines, prefer Bun's native file APIs.

🔎 Example refactor using Bun APIs

For checking existence:

-if (fs.existsSync(outDir)) {
+if (await Bun.file(path.join(outDir, "package.json")).exists()) {
   // Directory exists
}

For removing directories, you can use Bun's shell API:

-fs.rmSync(outDir, { recursive: true });
+await $`rm -rf ${outDir}`;

For creating directories:

-fs.mkdirSync(binDir, { recursive: true });
+await $`mkdir -p ${binDir}`;

As per coding guidelines, prefer Bun's native APIs over Node.js APIs.

Also applies to: 59-66, 100-100

apps/cli/src/utils/get-latest-cli-version.ts (1)

7-7: Use Bun.file instead of fs-extra for reading package.json.

The function uses fs-extra to read the package.json file. Per coding guidelines, prefer Bun's native file APIs.

🔎 Proposed refactor using Bun.file
-import fs from "fs-extra";
 import { PKG_ROOT } from "../constants";
 
 // This is replaced at compile time by bun build --define
 declare const CLI_VERSION: string | undefined;
 
 export const getLatestCLIVersion = (): string => {
   if (typeof CLI_VERSION !== "undefined") {
     return CLI_VERSION;
   }
 
   // Fallback to reading package.json (for npm distribution)
   try {
     const packageJsonPath = path.join(PKG_ROOT, "package.json");
-    const packageJsonContent = fs.readJSONSync(packageJsonPath);
+    const packageJsonContent = await Bun.file(packageJsonPath).json();
     return packageJsonContent.version ?? "1.0.0";
   } catch {
     return "1.0.0";
   }
 };

Note: This would require making the function async, or use the synchronous alternative:

const file = Bun.file(packageJsonPath);
const text = await file.text();
const packageJsonContent = JSON.parse(text);

As per coding guidelines, prefer Bun's native file APIs over Node.js-based libraries.

Also applies to: 19-25

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a69159 and eb5328c.

📒 Files selected for processing (22)
  • apps/cli/scripts/build.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/index.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/templates/examples/ai/native/bare/polyfills.js.hbs
  • apps/cli/templates/examples/ai/native/unistyles/polyfills.js.hbs
  • apps/cli/templates/examples/ai/native/uniwind/polyfills.js.hbs
  • apps/cli/templates/examples/todo/server/drizzle/mysql/src/schema/todo.ts.hbs
  • apps/cli/templates/examples/todo/server/drizzle/postgres/src/schema/todo.ts.hbs
  • apps/cli/templates/examples/todo/server/drizzle/sqlite/src/schema/todo.ts.hbs
  • apps/cli/templates/frontend/native/uniwind/global.css.hbs
  • apps/cli/templates/frontend/nuxt/app/assets/css/main.css.hbs
  • apps/cli/templates/frontend/react/react-router/react-router.config.ts.hbs
  • apps/cli/templates/frontend/react/react-router/src/routes.ts.hbs
  • apps/cli/templates/frontend/solid/index.html.hbs
  • apps/cli/templates/frontend/solid/src/components/loader.tsx.hbs
  • apps/cli/templates/frontend/solid/src/styles.css.hbs
  • apps/cli/templates/frontend/svelte/src/app.css.hbs
  • apps/cli/templates/frontend/svelte/src/app.d.ts.hbs
  • apps/cli/templates/frontend/svelte/src/app.html.hbs
  • apps/cli/templates/frontend/svelte/src/lib/index.ts.hbs
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cli/src/helpers/addons/addons-setup.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/constants.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/index.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/constants.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/index.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/constants.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/index.ts
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/constants.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/index.ts
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/constants.ts
  • apps/cli/src/utils/get-latest-cli-version.ts
  • apps/cli/scripts/build.ts
  • apps/cli/src/index.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Define functions using the standard function declaration syntax, not arrow functions

Applied to files:

  • apps/cli/src/utils/get-latest-cli-version.ts
📚 Learning: 2025-12-03T07:47:42.038Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/better-t-stack-repo.mdc:0-0
Timestamp: 2025-12-03T07:47:42.038Z
Learning: Applies to **/*.{ts,tsx} : Do not use explicit return types

Applied to files:

  • apps/cli/src/utils/get-latest-cli-version.ts
📚 Learning: 2025-12-03T07:48:14.714Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/convex_rules.mdc:0-0
Timestamp: 2025-12-03T07:48:14.714Z
Learning: Applies to convex/**/*.ts : ALWAYS use the new function syntax for Convex functions with explicit args, returns, and handler properties

Applied to files:

  • apps/cli/src/utils/get-latest-cli-version.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/cli/scripts/build.ts
📚 Learning: 2025-12-03T07:48:26.419Z
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun:sqlite` module for SQLite instead of `better-sqlite3`

Applied to files:

  • apps/cli/scripts/build.ts
🧬 Code graph analysis (1)
apps/cli/src/utils/get-latest-cli-version.ts (1)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (63-63)
🔇 Additional comments (4)
apps/cli/src/constants.ts (1)

63-63: LGTM!

The dynamic package root discovery is well-designed for supporting both development and compiled binary scenarios.

apps/cli/scripts/build.ts (2)

104-116: LGTM!

The Bun.build API usage is correct, with proper configuration for cross-compilation and compile-time defines. The CLI_VERSION define aligns with the consumption in get-latest-cli-version.ts.


68-77: No changes needed. The --os="*" --cpu="*" flags are supported by Bun's install command and work correctly for cross-platform installation of optionalDependencies. The code implementation is sound.

Likely an incorrect or invalid review comment.

apps/cli/src/index.ts (1)

1-48: LGTM!

The refactored public API surface is clean and well-documented. The module properly re-exports the programmatic API and necessary types, making it easier for consumers to use the CLI programmatically.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/cli/src/constants.ts (1)

24-24: Consider removing the explicit return type.

The coding guidelines specify not to use explicit return types in TypeScript files. TypeScript can infer the return type from the function body.

🔎 Suggested change
-function findPackageRoot(): string {
+function findPackageRoot() {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb5328c and bd6d873.

📒 Files selected for processing (1)
  • apps/cli/src/constants.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

Define functions using the standard function declaration syntax, not arrow functions

Files:

  • apps/cli/src/constants.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/better-t-stack-repo.mdc)

**/*.{ts,tsx}: Use TypeScript type aliases instead of interface declarations
Do not use explicit return types

Files:

  • apps/cli/src/constants.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

**/*.{ts,tsx,js,jsx}: Use bun <file> instead of node <file> or ts-node <file> for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
Use Bun.serve() which supports WebSockets, HTTPS, and routes instead of express
Use bun:sqlite module for SQLite instead of better-sqlite3
Use Bun.redis for Redis instead of ioredis
Use Bun.sql for Postgres instead of pg or postgres.js
Use built-in WebSocket instead of the ws package
Prefer Bun.file over node:fs readFile/writeFile methods
Use Bun.$ template literal syntax instead of execa for shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server with bun --hot <file> to enable hot reloading during development

Files:

  • apps/cli/src/constants.ts
**/*.{ts,tsx,js,jsx,css}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use bun build <file> instead of webpack or esbuild for bundling TypeScript, JavaScript, and CSS files

Files:

  • apps/cli/src/constants.ts
**/*.{html,tsx,ts,jsx,js}

📄 CodeRabbit inference engine (.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc)

Use HTML imports with Bun.serve() for frontend instead of Vite

Files:

  • apps/cli/src/constants.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx,css} : Use `bun build <file>` instead of `webpack` or `esbuild` for bundling TypeScript, JavaScript, and CSS files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to package.json : Use `bun run <script>` instead of `npm run <script>`, `yarn run <script>`, or `pnpm run <script>`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.$` template literal syntax instead of `execa` for shell command execution
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `bun <file>` instead of `node <file>` or `ts-node <file>` for running TypeScript/JavaScript files
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun:test` module with `test` and `expect` functions for writing tests
Learnt from: CR
Repo: AmanVarshney01/create-better-t-stack PR: 0
File: .cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-12-03T07:48:26.419Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use `Bun.serve()` which supports WebSockets, HTTPS, and routes instead of `express`
🔇 Additional comments (5)
apps/cli/src/constants.ts (5)

2-2: LGTM!

The import is appropriate for the synchronous file existence checks needed during initialization. The coding guideline's preference for Bun.file specifically applies to readFile/writeFile operations, not existsSync.


6-23: LGTM!

Excellent documentation that clearly explains the discovery logic and package structure for both development and production scenarios.


29-35: LGTM!

The development root discovery logic is clean and correct. When running from source at src/constants.ts, resolving to .. correctly finds the package root where templates/ resides.


37-58: Verify the discovery logic in actual deployment scenarios.

The directory traversal logic appears sound and handles multiple deployment patterns. However, given the complexity and the experimental nature of this change, ensure this works correctly when:

  1. The binary runs from node_modules/@better-t-stack/cli-{platform}-{arch}/bin/
  2. The templates are in the parent create-better-t-stack package
  3. Various npm/bunx cache locations are used

Consider testing with the actual compiled binaries in different installation scenarios (global install, local install, bunx execution) to confirm the discovery logic works as expected.


64-64: LGTM!

The dynamic package root discovery properly supports both development and compiled binary scenarios, aligning with the new Bun-based build and platform-package publishing workflow.

@AmanVarshney01
Copy link
Owner Author

this shit is not working!!

@AmanVarshney01 AmanVarshney01 marked this pull request as draft December 24, 2025 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants