-
-
Notifications
You must be signed in to change notification settings - Fork 262
EXPERIMENTAL: opentui rewrite #750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
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. Comment |
PR Preview ReleaseA preview version has been published for this PR.
Commit: 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@pr750NPM LinksTo publish a new preview after more commits, remove and re-add the |
There was a problem hiding this 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 dependencyconsola.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 returnsfalsewhen 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 ofexeca.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. Ifgit addorgit commitfail (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 multiplefs.existsSyncchecks 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, thefindBinary()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 readpackage.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
mapcallback 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 publishfailing.🔎 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 modulegetDefaultConfig(line 10) - not referencedpath(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.
DirectoryConflictandTemplatetypes 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: Placeholderaddcommand has defined options but no implementation.The
addcommand 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
addcommand 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.gzfor Linux and.zipfor 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@deprecatedtag for better tooling support.Adding a proper JSDoc deprecation annotation will cause IDEs and TypeScript to show deprecation warnings when the
initalias 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: innerpkgshadows outerpkg.The loop variable
pkgat line 158 shadows the outerpkgconstant 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:prepublishOnlywarning may be insufficient.The script only echoes a message but doesn't prevent accidental publishing without binaries. Consider either:
- Making it fail explicitly:
"exit 1"- 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
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (37)
.github/workflows/pr-preview.yaml.github/workflows/release.yamlapps/cli/bin/create-better-t-stackapps/cli/package.jsonapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/index.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/command-exists.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/errors.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/utils/open-url.tsapps/cli/test/test-utils.tsapps/cli/tsconfig.jsonapps/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.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/api.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/errors.tsapps/cli/src/index.tsapps/cli/test/test-utils.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/api.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/errors.tsapps/cli/src/index.tsapps/cli/test/test-utils.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --hot <file>to enable hot reloading during development
Files:
apps/cli/src/helpers/core/git.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/api.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/errors.tsapps/cli/src/index.tsapps/cli/test/test-utils.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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 ofwebpackoresbuildfor bundling TypeScript, JavaScript, and CSS files
Files:
apps/cli/src/helpers/core/git.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/api.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/errors.tsapps/cli/src/index.tsapps/cli/test/test-utils.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/api.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/errors.tsapps/cli/src/index.tsapps/cli/test/test-utils.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/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.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/tsconfig.jsonapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/open-url.tsapps/cli/bin/create-better-t-stackapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/tsconfig.jsonapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/test/test-utils.tsapps/cli/scripts/build.tsapps/cli/tsconfig.jsonapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/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.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/scripts/build.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/constants.tsapps/cli/src/utils/docker-utils.tsapps/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.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/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.
| "@opentui/core": "^0.1.62", | ||
| "@opentui/react": "^0.1.62", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| const dryRun = process.argv.includes("--dry-run"); | ||
| const tag = process.argv.includes("--tag") | ||
| ? process.argv[process.argv.indexOf("--tag") + 1] | ||
| : "latest"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| 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"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -30Repository: AmanVarshney01/create-better-t-stack
Length of output: 1295
🏁 Script executed:
cat -n apps/cli/package.json | head -50Repository: AmanVarshney01/create-better-t-stack
Length of output: 1489
🏁 Script executed:
cat -n apps/cli/scripts/publish.ts | head -100 | tail -50Repository: AmanVarshney01/create-better-t-stack
Length of output: 2107
🏁 Script executed:
grep -n "builtPackages" apps/cli/scripts/publish.tsRepository: AmanVarshney01/create-better-t-stack
Length of output: 387
🏁 Script executed:
cat -n apps/cli/scripts/build.tsRepository: 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.
| 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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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}`; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- 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}`;- 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}`;- 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.
apps/cli/src/tui/app.tsx
Outdated
| 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
There was a problem hiding this 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
📒 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
| - 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 }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| - 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.
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).
There was a problem hiding this 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.Zbase version. This could produce confusing versions for long branch names or fail ifpackage.jsonalready 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_VERSIONExample 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 -eto 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/distbefore 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
📒 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 publishsupportsNPM_CONFIG_TOKENand this is the recommended pattern for GitHub Actions, as documented in the official bun CLI reference. The workflow is using the correct approach.
| on: | ||
| push: | ||
| branches: | ||
| - "**" | ||
| paths: | ||
| - "apps/cli/**" | ||
| - "packages/types/**" | ||
| - ".github/workflows/pr-preview-push.yaml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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: 30Committable 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.
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| id-token: write |
There was a problem hiding this comment.
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.
| 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.
| - 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 }} | ||
|
|
There was a problem hiding this comment.
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.
| - 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).
There was a problem hiding this 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: Addpicocolorsto the dependency version map.The import of
picocolorsat line 3 is not declared inapps/cli/src/constants.tsunderdependencyVersionMap, 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 byrenderTuinever 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:
- Resolving/rejecting the Promise in
onCancelandonCompletehandlers instead of callingprocess.exit- Changing the return type to
voidand documenting that this function terminates the process
671-696: Usepath.joinfor 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'spathmodule and usepath.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.tsandtauri-setup.tswhich wrap Bun$commands in try/catch and calllog.erroron failure, this function lacks error handling. Ifoxlint --initoroxfmt --initfails, 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) andconsola.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,
useLoggeranduseLatestLogare already defined with thefunctionkeyword, 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
useStatewith computed initial values, lazy initialization avoids callinglogger.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
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (33)
apps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/prompts/addons.tsapps/cli/src/prompts/api.tsapps/cli/src/prompts/auth.tsapps/cli/src/prompts/backend.tsapps/cli/src/prompts/config-prompts.tsapps/cli/src/prompts/database-setup.tsapps/cli/src/prompts/database.tsapps/cli/src/prompts/examples.tsapps/cli/src/prompts/frontend.tsapps/cli/src/prompts/git.tsapps/cli/src/prompts/install.tsapps/cli/src/prompts/orm.tsapps/cli/src/prompts/package-manager.tsapps/cli/src/prompts/payments.tsapps/cli/src/prompts/project-name.tsapps/cli/src/prompts/runtime.tsapps/cli/src/prompts/server-deploy.tsapps/cli/src/prompts/web-deploy.tsapps/cli/src/tui/app.tsxapps/cli/src/tui/use-logger.tsapps/cli/src/utils/logger.tsapps/cli/src/utils/open-url.tsopentui
💤 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.tsapps/cli/src/utils/logger.tsapps/cli/src/tui/use-logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/utils/logger.tsapps/cli/src/tui/use-logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/project-config.tsapps/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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --hot <file>to enable hot reloading during development
Files:
apps/cli/src/helpers/core/git.tsapps/cli/src/utils/logger.tsapps/cli/src/tui/use-logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/project-config.tsapps/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 ofwebpackoresbuildfor bundling TypeScript, JavaScript, and CSS files
Files:
apps/cli/src/helpers/core/git.tsapps/cli/src/utils/logger.tsapps/cli/src/tui/use-logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/utils/logger.tsapps/cli/src/tui/use-logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/helpers/addons/addons-setup.tsapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/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.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/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.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/core/add-deployment.tsapps/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.tsapps/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.tsapps/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 ofexecafor 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.warnis appropriate given the removal of the log utilityBased on learnings,
Bun.$template literal syntax should be used instead ofexecafor 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 ofexeca.
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.infotoconsole.logwith 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 ofexecafor 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
execato Bun's$template literal aligns with the coding guidelines. Therawcommand 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 ofexeca. The error handling pattern is consistent withstarlight-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/promptslog 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
subscribefor easy cleanup. The copy ingetLogs()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.
| await $`git add -A`.cwd(projectDir).quiet(); | ||
| await $`git commit -m ${"initial commit"}`.cwd(projectDir).quiet(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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.
| {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} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| {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.
There was a problem hiding this 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/coredependency is pinned to^0.1.62, but the platform-specific native bindings inoptionalDependencies(lines 101-106) are pinned to0.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
⛔ Files ignored due to path filters (1)
bun.lockis 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.3to 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.
| "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" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- Node.js cannot execute
.tsfiles directly - Most consumers expect pre-compiled JavaScript with separate
.d.tstype definitions - 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'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| "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.
There was a problem hiding this 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 theatlas deployments setupcommand for consistency.Line 48 runs
atlas deployments setupwithout.cwd(serverDir), unlike all other database providers in this directory (prisma-postgres, neon, supabase). TheserverDirparameter 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_EXISTSerrors, 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 returndefaultConfig.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 indevUrlfallback.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 usescreate()from api.ts (line 102). Thecreate()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
addcommand 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
addcommand?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
queueMicrotaskfor 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
logsarray 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 useslog.error(...). Other setup files in this PR (e.g.,fumadocs-setup.ts,prisma-postgres-setup.ts) consistently use onlylog.errorfor 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 newlogutility 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
📒 Files selected for processing (23)
apps/cli/scripts/build.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/core/command-handlers.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/utils/logger.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/render-title.tsapps/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.tsapps/cli/src/utils/sponsors.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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.tsapps/cli/src/utils/sponsors.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --hot <file>to enable hot reloading during development
Files:
apps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/sponsors.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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 ofwebpackoresbuildfor bundling TypeScript, JavaScript, and CSS files
Files:
apps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/utils/sponsors.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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.tsapps/cli/src/utils/sponsors.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/cli.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/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.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/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.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/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/promptsto 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 withlog.error→log.successprovides 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
$frombunandlogfrom the centralized logger aligns with the coding guidelines for usingBun.$template literal syntax instead ofexeca.
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 usesBun.$template literal syntax instead ofexeca.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
templateparameter with a sensible default aligns with the removal of interactive prompts. UsesBun.$as per coding guidelines.
24-34: LGTM! Execution and error handling are consistent with other addon setups.The pattern of using
log.errorfor the high-level message andconsole.errorwithpc.redfor the detailed error message is consistent withwxt-setup.tsandruler-setup.ts.apps/cli/src/helpers/addons/wxt-setup.ts (2)
2-11: LGTM! Consistent migration to Bun-based execution.The import of
$frombun, logger integration, and updated function signature with template parameter follows the same pattern as other addon setup files. UsesBun.$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 buncorrectly 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
openUrlutility in thedocsandbuildercommands 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
$frombunandlogfrom the centralized logger follows the established pattern. UsesBun.$as per coding guidelines.
37-40: LGTM! Updated function signature with agents parameter.The removal of interactive prompt flow in favor of an explicit
agentsparameter 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
logconvenience 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 parameterizedtemplateargument withTEMPLATE_VALUESmapping aligns well with the PR's goal of supporting a programmatic API. TheCI: "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:
PrismaPostgresSetupOptionstype for parameterized configurationsetupWithCreateDbfor 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
SupabaseSetupOptionstype alias- Captures stdout from
supabase startto 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
NeonSetupOptionswith sensible defaults formode,setupMethod,projectName, andregionId. 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
MongoDBAtlasSetupOptionswith 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:--integrationsargument format may need adjustment.According to learnings from this repository, the Ultracite CLI's
--integrationsflag 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
logutility and returns a boolean to indicate success/failure, enabling proper fallback handling in the caller.
16-20: LGTM: Well-designed options type.The
TursoSetupOptionstype 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.
| 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"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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
- Ruler — AI Expertise (intellectronica) — Ruler docs. [online].
- GitHub — intellectronica/ruler repository (Supported AI Agents section). [online].
- 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.
There was a problem hiding this 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: Usepath.joininstead 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: Usepath.joinfor projectDir path construction.Line 785 also uses string concatenation with
/for path construction. This should be updated along with line 696 to usepath.joinfor 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: Removeprocess.exit(0)calls to allow graceful shutdown.While the Promise now calls
resolve(), theprocess.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 directprocess.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
onCompletethrows 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
resolveJsonModuleintsconfig.jsonif not already enabled.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --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 ofwebpackoresbuildfor 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.
apps/cli/src/tui/app.tsx
Outdated
| 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 }[]; | ||
| } |
There was a problem hiding this comment.
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.
| 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 }[]; | |
| }; |
ffee16a to
2583611
Compare
There was a problem hiding this 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_EXISTSerrors, the while loop exits normally without executing thebreakstatement. This means:
- No env file is written (the
writeEnvFilecalls on lines 241-244 never execute)- Line 257 claims "setup completed successfully" even though no database was created
- 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 theexpectErrorconfiguration flag from test config to thecreate()API call.The test cases are correctly configured with
expectError: true, but therunTRPCTestfunction never forwards this flag to thecreate()API (lines 99–117). This meanscreate()doesn't know it should trigger validation errors, causing it to returnsuccess: truewhen tests expectsuccess: false. AddexpectError: config.expectErrorto thecreate()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 forgit initabove.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/rulerlibrary 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
--tagis the last argument or followed by another flag,process.argv[indexOf + 1]will beundefinedor 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
optionalDependenciesentries (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 usecd apps/cliandcd 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 publishfails. Withoutset -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: Usepath.joinfor projectDir path construction.String concatenation with
/won't work correctly on Windows. Usepath.joinfor 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: Usepath.joininstead of string concatenation for paths.String concatenation with
/won't work correctly on Windows. Usepath.joinfor 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/coreand platform-specific packages.The main dependency uses
"@opentui/core": "^0.1.62"but the optional platform bindings pin to0.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
srcdirectory and pointsmain,types, andexportsto TypeScript source files (./src/index.ts). This configuration will fail for published packages because:
- Node.js cannot execute
.tsfiles directly- Most consumers expect pre-compiled JavaScript with separate
.d.tstype definitions- 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
prepublishOnlyscript 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.errorhere is inconsistent with the rest of the file which uses thelogutility. While this might be intentional to preserve the full error object output, consider usinglog.error()for consistency or adding a comment explaining whyconsole.erroris 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 centralizedloghelper from../../utils/logger. Usingconsole.logdirectly 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 usingBun.filefor reading package.json.Per coding guidelines, prefer
Bun.fileovernode:fsreadFile methods. Since this is a Bun-specific build script, usingBun.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
fsfor other operations likeexistsSync,rmSync,mkdirSync, andstatSync, 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
getLatestCLIVersionsuggests it fetches the latest version from npm, but it actually returns the current installed/compiled version. Consider renaming togetCLIVersionorgetCurrentCLIVersionfor 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 "). IfstepTextdoesn'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
hasNextis true, the URL ishttp://localhost:3001, and the final fallback is alsohttp://localhost:3001. This makes thehasNextcheck 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 usesconsole.error()for the detailed error message. For consistency, consider usinglog.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@deprecatedJSDoc tag.The backwards compatibility export is thoughtful, but the deprecation notice is only in a comment. Adding a formal
@deprecatedJSDoc 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
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (68)
.github/workflows/pr-preview-push.yaml.github/workflows/pr-preview.yaml.github/workflows/release.yamlapps/cli/bin/create-better-t-stackapps/cli/package.jsonapps/cli/scripts/build.tsapps/cli/scripts/publish.tsapps/cli/src/api.tsapps/cli/src/cli.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/helpers/addons/starlight-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/tui-setup.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/core/add-deployment.tsapps/cli/src/helpers/core/command-handlers.tsapps/cli/src/helpers/core/convex-codegen.tsapps/cli/src/helpers/core/create-project.tsapps/cli/src/helpers/core/db-setup.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/core/install-dependencies.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/helpers/database-providers/mongodb-atlas-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/index.tsapps/cli/src/prompts/addons.tsapps/cli/src/prompts/api.tsapps/cli/src/prompts/auth.tsapps/cli/src/prompts/backend.tsapps/cli/src/prompts/config-prompts.tsapps/cli/src/prompts/database-setup.tsapps/cli/src/prompts/database.tsapps/cli/src/prompts/examples.tsapps/cli/src/prompts/frontend.tsapps/cli/src/prompts/git.tsapps/cli/src/prompts/install.tsapps/cli/src/prompts/orm.tsapps/cli/src/prompts/package-manager.tsapps/cli/src/prompts/payments.tsapps/cli/src/prompts/project-name.tsapps/cli/src/prompts/runtime.tsapps/cli/src/prompts/server-deploy.tsapps/cli/src/prompts/web-deploy.tsapps/cli/src/tui/app.tsxapps/cli/src/tui/use-logger.tsapps/cli/src/utils/command-exists.tsapps/cli/src/utils/docker-utils.tsapps/cli/src/utils/errors.tsapps/cli/src/utils/file-formatter.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/utils/logger.tsapps/cli/src/utils/open-url.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/render-title.tsapps/cli/src/utils/sponsors.tsapps/cli/test/test-utils.tsapps/cli/tsconfig.jsonapps/cli/tsdown.config.tsopentui
💤 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.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/errors.tsapps/cli/test/test-utils.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/index.tsapps/cli/scripts/publish.tsapps/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.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/errors.tsapps/cli/test/test-utils.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/index.tsapps/cli/scripts/publish.tsapps/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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --hot <file>to enable hot reloading during development
Files:
apps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/errors.tsapps/cli/test/test-utils.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/index.tsapps/cli/scripts/publish.tsapps/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 ofwebpackoresbuildfor bundling TypeScript, JavaScript, and CSS files
Files:
apps/cli/src/helpers/addons/oxlint-setup.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/errors.tsapps/cli/test/test-utils.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/index.tsapps/cli/scripts/publish.tsapps/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.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/utils/project-directory.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/utils/errors.tsapps/cli/test/test-utils.tsapps/cli/src/utils/logger.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/database-providers/turso-setup.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/src/helpers/core/project-config.tsapps/cli/src/index.tsapps/cli/scripts/publish.tsapps/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.tsapps/cli/src/utils/command-exists.tsapps/cli/src/helpers/database-providers/supabase-setup.tsapps/cli/src/helpers/addons/ultracite-setup.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/tui/app.tsxapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/helpers/core/git.tsapps/cli/src/helpers/addons/ruler-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/utils/open-url.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/cli/scripts/publish.tsapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/helpers/addons/wxt-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/cli/scripts/publish.tsapps/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.tsapps/cli/src/helpers/core/add-addons.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/constants.tsapps/cli/package.jsonapps/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.tsapps/cli/src/helpers/database-providers/neon-setup.tsapps/cli/src/helpers/addons/fumadocs-setup.tsapps/cli/src/helpers/database-providers/prisma-postgres-setup.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/constants.tsapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/cli/package.jsonapps/cli/src/helpers/core/project-config.tsapps/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.tsapps/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.tsapps/cli/src/helpers/addons/tauri-setup.tsapps/cli/src/constants.tsapps/cli/scripts/build.tsapps/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.tsxapps/cli/src/helpers/core/git.tsapps/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.tsxapps/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.tsapps/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.
| 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); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -A2Repository: 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.tsRepository: 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 -A1Repository: 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 -A2Repository: 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.tsRepository: 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.
| 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, read the actual file to confirm the current state
cat -n apps/cli/src/utils/file-formatter.tsRepository: 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 -A2Repository: 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 -A2Repository: AmanVarshney01/create-better-t-stack
Length of output: 107
🏁 Script executed:
# Search for formatFile without type restrictions
rg -n 'formatFile' -B2 -A2Repository: 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 -A1Repository: 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 -20Repository: 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.tsRepository: 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.tsRepository: AmanVarshney01/create-better-t-stack
Length of output: 657
Remove explicit return type and simplify to synchronous function.
This function has several fixable issues:
-
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. -
Unnecessary async wrapper: The function is declared
asyncbut performs no asynchronous operations. Removeasyncand returnPromisewrapper. -
Return type inconsistency: The signature declares
| nullbut always returnscontent(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.
| 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.
| export interface LogEntry { | ||
| id: number; | ||
| level: LogLevel; | ||
| message: string; | ||
| timestamp: Date; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| 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); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
+ });
}2583611 to
6a69159
Compare
There was a problem hiding this 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 thecreate()API before callingcreateProject().The
create()function builds a configuration but never validates it, allowing invalid combinations (e.g., drizzle + mongodb) to pass through successfully. This causes tests usingexpectError()to fail—they expectresult.successto befalse, but the API returnssuccess: truefor invalid configs. Import and callvalidateConfigForProgrammaticUse(config)from./utils/config-validationimmediately beforecreateProject(config)so that validation errors are caught and returned withsuccess: false.Also, convert
TestConfigandTestResultfrominterfacetotypedeclarations 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:
Explicit return type violation: Line 7 declares
: Promise<string | null>, but per coding guidelines, TypeScript files should not use explicit return types.Unnecessary async: The function is declared
asyncbut contains no asynchronous operations—it immediately returns the input.Dead code in return type: The
| nullunion is never used; the function always returnscontent(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 forgit initon 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
actionis"rename", the recursive call at line 58 doesn't forward theoptionsparameter: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, andhandleErrorhave explicit: neverreturn 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--tagis the last argument.If
--tagis provided as the last argument without a value,process.argv[indexOf + 1]will beundefined, andtagbecomesundefinedrather 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. Ifpackage.jsoncontains 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 returndefaultConfig.X. Simplify tooptions.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/coreand platform-specific packages.The main dependency uses
"@opentui/core": "^0.1.62"but the optional platform bindings pin to0.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, andexportsto 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
prepublishOnlyscript 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: Usepath.joininstead of string concatenation for paths.String concatenation with
/won't work correctly on Windows. Usepath.joinfor 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: Usepath.joinfor projectDir path construction.Same issue as above - string concatenation with
/should be replaced withpath.joinfor 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/rulerlibrary. 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
pcimport frompicocolorsis 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()returnstruebut 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:
- Throwing an error if all compiled binary paths fail
- 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
templateparameter 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 centralizedlog.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.errorinstead ofconsola.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 movingframesarray outside the component.The
framesarray 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
CreateOptionsandCreateResultuseinterface.🔎 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 exportapps/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
runfunction is defined correctly, but the fallback on line 30 whenresult.statusis 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_PATHoverride 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
warncase uses a hardcoded hex color#f59e0bwhile all other cases usetheme.*constants. Consider adding awarnorwarningproperty 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" (fromlogger.ts), butgetLogIcondoesn'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 unuseduseStateimport.The
useStatehook 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.optionsis empty, pressing return on line 24 would cause a runtime error when accessingprops.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 forkeybinds.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, ifprops.optionsis empty, the space key handler on line 19 would throw when accessingprops.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 -eto 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-*/; doapps/cli/src/cli.ts (2)
14-32: Remove unused type imports.
DirectoryConflictandTemplateare imported but not used in this file. Additionally,pathis 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: Placeholderaddcommand implementation.The
addcommand 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
addcommand or open an issue to track this?
| - 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 }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
| 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 }[]; | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| 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"; | ||
| } | ||
| }; |
There was a problem hiding this comment.
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:
- Functions should use standard function declaration syntax, not arrow functions
- 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.
| 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.
There was a problem hiding this 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()fromnode:fsfor 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
fsfromnode:fsfor 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-extrato 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
📒 Files selected for processing (22)
apps/cli/scripts/build.tsapps/cli/src/constants.tsapps/cli/src/helpers/addons/addons-setup.tsapps/cli/src/index.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/templates/examples/ai/native/bare/polyfills.js.hbsapps/cli/templates/examples/ai/native/unistyles/polyfills.js.hbsapps/cli/templates/examples/ai/native/uniwind/polyfills.js.hbsapps/cli/templates/examples/todo/server/drizzle/mysql/src/schema/todo.ts.hbsapps/cli/templates/examples/todo/server/drizzle/postgres/src/schema/todo.ts.hbsapps/cli/templates/examples/todo/server/drizzle/sqlite/src/schema/todo.ts.hbsapps/cli/templates/frontend/native/uniwind/global.css.hbsapps/cli/templates/frontend/nuxt/app/assets/css/main.css.hbsapps/cli/templates/frontend/react/react-router/react-router.config.ts.hbsapps/cli/templates/frontend/react/react-router/src/routes.ts.hbsapps/cli/templates/frontend/solid/index.html.hbsapps/cli/templates/frontend/solid/src/components/loader.tsx.hbsapps/cli/templates/frontend/solid/src/styles.css.hbsapps/cli/templates/frontend/svelte/src/app.css.hbsapps/cli/templates/frontend/svelte/src/app.d.ts.hbsapps/cli/templates/frontend/svelte/src/app.html.hbsapps/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.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/scripts/build.tsapps/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.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/scripts/build.tsapps/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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --hot <file>to enable hot reloading during development
Files:
apps/cli/src/constants.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/scripts/build.tsapps/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 ofwebpackoresbuildfor bundling TypeScript, JavaScript, and CSS files
Files:
apps/cli/src/constants.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/scripts/build.tsapps/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.tsapps/cli/src/utils/get-latest-cli-version.tsapps/cli/scripts/build.tsapps/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_VERSIONdefine aligns with the consumption inget-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.
There was a problem hiding this 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
📒 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}: Usebun <file>instead ofnode <file>orts-node <file>for running TypeScript/JavaScript files
Bun automatically loads .env files, so don't use the dotenv package
UseBun.serve()which supports WebSockets, HTTPS, and routes instead ofexpress
Usebun:sqlitemodule for SQLite instead ofbetter-sqlite3
UseBun.redisfor Redis instead ofioredis
UseBun.sqlfor Postgres instead ofpgorpostgres.js
Use built-inWebSocketinstead of thewspackage
PreferBun.fileovernode:fsreadFile/writeFile methods
UseBun.$template literal syntax instead ofexecafor shell command execution
Import .css files directly in TypeScript/JavaScript files; Bun's CSS bundler will handle bundling
Run server withbun --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 ofwebpackoresbuildfor 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.filespecifically applies to readFile/writeFile operations, notexistsSync.
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 wheretemplates/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:
- The binary runs from
node_modules/@better-t-stack/cli-{platform}-{arch}/bin/- The templates are in the parent
create-better-t-stackpackage- 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.
|
this shit is not working!! |
Summary by CodeRabbit
New Features
Bug Fixes & Improvements
✏️ Tip: You can customize this high-level summary in your review settings.