Skip to content

Conversation

@therealsamyak
Copy link

@therealsamyak therealsamyak commented Dec 7, 2025

Sorry for jumping the gun here, but I will say I started working on this ~24 hours ago, and within that time lefthook is now used within BTS itself, so hopefully its fine 😅.

Add new cli flag --git-hooks, which supports { lefthook, husky, none }. Modified addons section to remove husky to compensate.

Areas Updates

  • *.md files across GitHub repo
  • Documentation (CLI-Commands, CLI-Programmatic-API, CLI-Options Reference, bts.jsonc)
  • CLI (added new Git Hooks section)
    • added prepare script with lefthook install to package.json in template.
  • Stack Builder (added new Git Hooks section)

Notes

  • You can only select one of { lefthook, husky, none }
    • 'None' is set to the default
  • "Fast and powerful Git hooks manager" is taken directly from Lefthook's GitHub description https://github.com/evilmartians/lefthook/.
  • If Ultracite is configured, Ultracite handles Git hooks setup instead.
    • There is a "bug" / missing feature in Ultracite where a prepare script in the package.json is not generated. I filed a feature request within the Ultracite repo (Prepare script when using Git hooks manager (ex. Lefthook) haydenbleasel/ultracite#427) so hopefully this is resolved soon. Ultracite already runs 'lefthook install' (or similar hook scripts) upon finishing its setup, so not a huge huge problem if the Git hooks don't change.
  • If not Ultracite, and Biome or Oxlint is configured, the pre-commit hooks are populated with lint-staged (husky), or the specific lint commands biome check --write and/or oxlint --fix . (lefthook) respectively. Lefthook doesn't need lint-staged (just use stage_fixed: true), so why add another dependency when it's not necessary.
  • The logo for lefthook can be found here https://github.com/evilmartians/lefthook/blob/master/logo.svg. Not sure how to add it xd.
  • Removed husky from the add command. There is possibility of expanding add command to also add a Git hooks manager, but it feels too complicated, just do bun add lefthook and its basically done for you xd
  • Currently you are allowed to select Husky without requiring an init of a git repo, even though git hooks don't work unless you init a git repo. I maintained that behavior here, but it is something to consider changing later down the line.

Disclaimer that majority of the code is AI-generated, but I did test it throughly, reviewed all the code generated manually with my own 2 eyes, and tested it locally to verify it worked before opening this PR.

Screenshots

image image image - wording can change here image image image

Summary by CodeRabbit

  • New Features

    • Added --git-hooks option to choose git hooks manager (lefthook, husky, none); Lefthook available as an alternative
  • Documentation

    • Updated CLI docs, programmatic API docs, README, and onboarding to document git-hooks option and examples
  • Chores

    • Removed Husky from addons list and consolidated hook tooling under a new Git Hooks category; presets and UI options updated to include gitHooks
  • Tests

    • Added comprehensive tests for lefthook, husky, and none configurations

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

@vercel
Copy link

vercel bot commented Dec 7, 2025

@therealsamyak is attempting to deploy a commit to the Better T Stack Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Walkthrough

Moves Husky out of the Addons list into a new Git Hooks feature; adds --git-hooks CLI option, GitHooks types/config fields, Lefthook support and templates, a git-hooks setup module (Husky/Lefthook), scaffolding wiring, docs updates, and test adjustments to use gitHooks.

Changes

Cohort / File(s) Summary
Types & public surface
apps/cli/src/types.ts, apps/cli/src/index.ts, apps/web/content/docs/cli/programmatic-api.mdx
Add GitHooksSchema/GitHooks type; remove husky from AddonsSchema; add gitHooks to Create/Add inputs, ProjectConfig, and public exports.
CLI flags, prompts & docs
README.md, apps/cli/README.md, apps/web/content/docs/cli/index.mdx, apps/web/content/docs/cli/options.mdx, apps/web/content/docs/index.mdx, apps/cli/src/prompts/git-hooks.ts, apps/cli/src/prompts/config-prompts.ts, apps/cli/src/prompts/addons.ts, apps/cli/src/validation.ts
Introduce --git-hooks option and getGitHooksChoice prompt; wire gitHooks into gatherConfig; remove husky from addon UI; add hooks to validation; update docs and README tables.
Config plumbing & defaults
apps/cli/src/constants.ts, apps/cli/src/utils/config-processing.ts, apps/cli/src/utils/bts-config.ts, apps/cli/src/utils/display-config.ts, apps/cli/src/helpers/core/add-addons.ts, apps/cli/src/helpers/core/detect-project-config.ts, apps/cli/src/helpers/core/command-handlers.ts
Add gitHooks to DEFAULT_CONFIG_BASE and dependencyVersionMap (lefthook); persist/serialize gitHooks; thread gitHooks through detection, processing, error paths and display.
Git-hooks implementation & templates
apps/cli/src/helpers/git-hooks/git-hooks-setup.ts, apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs
New module setupGitHooks with setupHusky and setupLefthook; Lefthook Handlebars template added; installs deps, updates package.json, and writes lefthook.yml as appropriate.
Scaffolding & template wiring
apps/cli/src/helpers/core/create-project.ts, apps/cli/src/helpers/core/template-manager.ts, apps/cli/src/helpers/addons/addons-setup.ts, apps/cli/src/helpers/addons/ultracite-setup.ts, apps/cli/src/helpers/core/create-readme.ts, apps/cli/src/helpers/core/post-installation.ts
Wire setupGitHooks and setupGitHooksTemplate into project scaffold; remove older setupHusky export from addons-setup; refactor Ultracite integration to use config.gitHooks; pass gitHooks into README/features and post-installation messages.
Web UI / presets & URL state
apps/web/src/lib/constant.ts, apps/web/src/lib/types.ts, apps/web/src/lib/stack-url-keys.ts, apps/web/src/lib/stack-url-state.client.ts, apps/web/src/lib/stack-url-state.ts, apps/web/src/lib/stack-utils.ts
Add gitHooks tech option and StackState field; remove husky from addons; add gitHooks to DEFAULT_STACK and presets; add URL parsers/keys and CLI generation for --git-hooks; update stack utils ordering.
README, templates & small docs
README.md, apps/cli/README.md, apps/cli/templates/addons/ruler/.ruler/bts.md.hbs, apps/web/content/docs/project-structure.mdx
Move Husky into Git Hooks section in readmes and onboarding templates; remove Husky from addon lists and examples; add hooks field in docs snippets.
Tests
apps/cli/test/git-hooks.test.ts, apps/cli/test/addons.test.ts, apps/cli/test/benchmark.test.ts, apps/cli/test/backend-runtime.test.ts, apps/cli/test/integration.test.ts, apps/cli/test/test-utils.ts
Add git-hooks-focused tests; remove husky from addon arrays and introduce gitHooks fields across tests; extend test defaults/types to include gitHooks.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant TemplateMgr as Template Manager
    participant FS as File System
    participant PM as Package Manager

    User->>CLI: init --git-hooks=<lefthook|husky|none>
    CLI->>CLI: validate flags & assemble ProjectConfig (includes gitHooks)
    CLI->>TemplateMgr: scaffold templates (addons, ultracite, etc.)
    TemplateMgr->>FS: copy template files
    CLI->>CLI: invoke setupGitHooks(ProjectConfig)
    alt ultracite manages hooks OR gitHooks == "none"
        CLI-->>PM: skip hook installation
    else gitHooks == "husky"
        CLI->>PM: install devDeps ["husky","lint-staged"]
        CLI->>FS: update package.json (prepare script, lint-staged)
        CLI->>FS: write husky configs (if any)
    else gitHooks == "lefthook"
        CLI->>PM: install devDep ["lefthook"]
        CLI->>FS: render lefthook.yml from template (biome/oxlint flags)
        CLI->>FS: update package.json (prepare script for lefthook)
    end
    CLI->>User: complete scaffolding
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (dependency installs, package.json edits, template rendering).
    • Template-manager wiring (setupGitHooksTemplate) and when templates are skipped (ultracite interplay).
    • Type and config propagation: ProjectConfig/types.ts, create-project.ts, and detection/processing paths.
    • Tests: git-hooks.test.ts and integration adjustments for correct fixtures.

Possibly related PRs

Poem

🐰
I hopped through templates late at night,
Moved Husky out and set hooks right.
Lefthook or Husky — pick your tune,
Templates stitched beneath the moon. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding lefthook support and refactoring git hooks into a separate configuration section.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
apps/web/src/lib/stack-url-keys.ts (1)

17-17: Consider abbreviating the URL parameter for consistency.

While functionally correct, the mapping gitHooks: "gitHooks" uses the full property name as the URL parameter. Most other mappings use abbreviations (e.g., webFrontend: "fe-w", runtime: "rt", backend: "be"). Consider using an abbreviated form like gitHooks: "gh" to maintain consistency and reduce URL length.

apps/web/src/lib/stack-utils.ts (1)

18-18: Verify the position of gitHooks in CATEGORY_ORDER.

The gitHooks category is placed after packageManager and before addons. While this ordering seems reasonable, consider whether it should be grouped closer to the "git" option (line 21) since they're conceptually related.

Consider this alternative ordering if you want to group Git-related options together:

  "packageManager",
+  "git",
+  "gitHooks",
-  "gitHooks",
  "addons",
  "examples",
-  "git",
  "install",
apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1)

87-97: Consider adding error handling for template operations.

If the Handlebars template file is missing or unreadable, this will throw an unhandled error with a potentially cryptic message. Consider wrapping in try-catch with a descriptive error, consistent with the pattern in createReadme (line 24 in create-readme.ts).

+  try {
    // Read and compile Handlebars template
    const templatePath = path.join(PKG_ROOT, "templates/git-hooks/lefthook/lefthook.yml.hbs");
    const templateContent = await fs.readFile(templatePath, "utf-8");
    const template = Handlebars.compile(templateContent);

    // Generate lefthook.yml content using template
    const lefthookYmlContent = template({ biome, oxlint });

    const lefthookYmlPath = path.join(projectDir, "lefthook.yml");
    await fs.writeFile(lefthookYmlPath, lefthookYmlContent);
+  } catch (error) {
+    throw new Error(`Failed to setup lefthook configuration: ${error}`);
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89d4a98 and c74d8fe.

📒 Files selected for processing (41)
  • README.md (1 hunks)
  • apps/cli/README.md (3 hunks)
  • apps/cli/src/constants.ts (2 hunks)
  • apps/cli/src/helpers/addons/addons-setup.ts (1 hunks)
  • apps/cli/src/helpers/addons/ultracite-setup.ts (3 hunks)
  • apps/cli/src/helpers/core/add-addons.ts (1 hunks)
  • apps/cli/src/helpers/core/command-handlers.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (4 hunks)
  • apps/cli/src/helpers/core/create-readme.ts (5 hunks)
  • apps/cli/src/helpers/core/detect-project-config.ts (1 hunks)
  • apps/cli/src/helpers/core/post-installation.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1 hunks)
  • apps/cli/src/index.ts (3 hunks)
  • apps/cli/src/prompts/addons.ts (2 hunks)
  • apps/cli/src/prompts/config-prompts.ts (5 hunks)
  • apps/cli/src/prompts/git-hooks.ts (1 hunks)
  • apps/cli/src/types.ts (5 hunks)
  • apps/cli/src/utils/bts-config.ts (2 hunks)
  • apps/cli/src/utils/config-processing.ts (2 hunks)
  • apps/cli/src/utils/display-config.ts (1 hunks)
  • apps/cli/src/validation.ts (1 hunks)
  • apps/cli/templates/addons/ruler/.ruler/bts.md.hbs (1 hunks)
  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs (1 hunks)
  • apps/cli/test/addons.test.ts (2 hunks)
  • apps/cli/test/backend-runtime.test.ts (1 hunks)
  • apps/cli/test/benchmark.test.ts (1 hunks)
  • apps/cli/test/git-hooks.test.ts (1 hunks)
  • apps/cli/test/integration.test.ts (4 hunks)
  • apps/cli/test/test-utils.ts (2 hunks)
  • apps/web/content/docs/cli/index.mdx (1 hunks)
  • apps/web/content/docs/cli/options.mdx (2 hunks)
  • apps/web/content/docs/cli/programmatic-api.mdx (1 hunks)
  • apps/web/content/docs/index.mdx (1 hunks)
  • apps/web/content/docs/project-structure.mdx (1 hunks)
  • apps/web/src/lib/constant.ts (9 hunks)
  • apps/web/src/lib/stack-url-keys.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.client.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.ts (1 hunks)
  • apps/web/src/lib/stack-utils.ts (2 hunks)
  • apps/web/src/lib/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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/web/src/lib/types.ts
  • apps/cli/src/prompts/addons.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/index.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/types.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/web/src/lib/constant.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/web/src/lib/types.ts
  • apps/cli/src/prompts/addons.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/index.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/types.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/web/src/lib/constant.ts
**/*.{ts,tsx,js,jsx}

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

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

Files:

  • apps/web/src/lib/types.ts
  • apps/cli/src/prompts/addons.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/index.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/types.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/web/src/lib/constant.ts
**/*.{ts,tsx,js,jsx,css}

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

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

Files:

  • apps/web/src/lib/types.ts
  • apps/cli/src/prompts/addons.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/index.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/types.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/web/src/lib/constant.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/web/src/lib/types.ts
  • apps/cli/src/prompts/addons.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/src/index.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/types.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/web/src/lib/constant.ts
**/*.hbs

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

**/*.hbs: In Handlebars templates, avoid generic if/else blocks. Write explicit conditions, such as: use if (eq orm "prisma") for Prisma, and else if (eq orm "drizzle") for Drizzle
Escape the '{{' in Handlebars templates like '{{'

Files:

  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs
**/*.test.{ts,tsx,js,jsx}

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

**/*.test.{ts,tsx,js,jsx}: Use bun test instead of jest or vitest for running tests
Use bun:test module with test and expect functions for writing tests

Files:

  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/test/addons.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/integration.test.ts
🧠 Learnings (4)
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
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/test/test-utils.ts
  • apps/cli/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:14.703Z
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.703Z
Learning: Applies to convex/**/*.ts : Use the api object from convex/_generated/api.ts to call public functions registered with query, mutation, or action

Applied to files:

  • apps/cli/src/helpers/core/create-readme.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
Learning: Applies to {package.json,bun.lockb} : Use `bun install` instead of `npm install`, `yarn install`, or `pnpm install`

Applied to files:

  • apps/web/content/docs/cli/index.mdx
🧬 Code graph analysis (10)
apps/web/src/lib/stack-url-state.client.ts (1)
apps/web/src/lib/constant.ts (2)
  • StackState (740-761)
  • DEFAULT_STACK (763-784)
apps/cli/src/index.ts (1)
apps/cli/src/types.ts (1)
  • GitHooksSchema (88-88)
apps/cli/src/prompts/git-hooks.ts (3)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
apps/cli/src/constants.ts (1)
  • DEFAULT_CONFIG (41-41)
apps/cli/src/utils/errors.ts (1)
  • exitCancelled (17-23)
apps/cli/src/helpers/addons/ultracite-setup.ts (2)
apps/cli/src/types.ts (1)
  • ProjectConfig (167-188)
apps/cli/src/utils/add-package-deps.ts (1)
  • addPackageDependency (6-57)
apps/cli/src/types.ts (1)
apps/cli/src/index.ts (1)
  • GitHooks (256-256)
apps/cli/test/git-hooks.test.ts (1)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
apps/cli/src/helpers/core/create-readme.ts (2)
apps/cli/src/index.ts (1)
  • GitHooks (256-256)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
apps/web/src/lib/stack-url-state.ts (1)
apps/web/src/lib/constant.ts (2)
  • StackState (740-761)
  • DEFAULT_STACK (763-784)
apps/cli/src/helpers/core/template-manager.ts (2)
apps/cli/src/types.ts (1)
  • ProjectConfig (167-188)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (7-7)
apps/cli/src/helpers/core/create-project.ts (2)
apps/cli/src/helpers/core/template-manager.ts (1)
  • setupGitHooksTemplate (599-610)
apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1)
  • setupGitHooks (8-34)
🔇 Additional comments (58)
apps/cli/templates/addons/ruler/.ruler/bts.md.hbs (1)

119-119: LGTM!

The removal of Husky from the addons list aligns with the PR's objective to move Git hooks to a dedicated section. The documentation now accurately reflects the new structure.

README.md (1)

47-48: LGTM!

The updated documentation clearly reflects the architectural change, separating Git hooks management from addons. The addition of Lefthook as an option alongside Husky provides users with flexibility.

apps/cli/src/helpers/core/post-installation.ts (3)

22-22: LGTM!

The addition of gitHooks to the destructured config properly integrates the new Git hooks feature into the post-installation flow.


30-30: LGTM!

The renamed condition hasHooksOrBiome correctly handles the new gitHooks configuration. The logic properly evaluates to true when gitHooks is set to either "husky" or "lefthook", and false when it's "none", while maintaining the fallback check for Biome.


46-46: LGTM!

The updated reference to hasHooksOrBiome ensures linting instructions are displayed when either Git hooks or Biome is configured.

apps/cli/src/helpers/core/command-handlers.ts (1)

105-105: LGTM!

The addition of gitHooks: "none" to the error path configuration properly satisfies the updated ProjectConfig type. Using "none" as the default is appropriate for error scenarios.

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

27-27: LGTM!

Setting gitHooks: "none" as the default is appropriate, making Git hooks management opt-in rather than forced upon users.

apps/cli/src/prompts/git-hooks.ts (1)

1-34: LGTM!

The implementation follows best practices:

  • Uses standard function declaration syntax as per coding guidelines
  • Implements efficient early return when gitHooks is already defined
  • Provides clear, descriptive labels and hints for each option
  • Properly handles user cancellation
  • Uses the appropriate default from DEFAULT_CONFIG.gitHooks
apps/cli/src/validation.ts (1)

21-21: Verify flag name consistency.

The addition of "hooks" to CORE_STACK_FLAGS should match the actual CLI flag name. Other entries in this set use the full config property names (e.g., "database", "backend", "gitHooks"). Please verify whether the CLI flag is defined as --hooks or --git-hooks and ensure consistency.

apps/cli/src/prompts/addons.ts (1)

66-66: LGTM! Clean removal of Husky from addons.

The removal of "husky" from the Other addons group is consistent with the PR's refactoring of Git hooks into a dedicated feature. The change aligns with the new --git-hooks option.

apps/web/content/docs/cli/programmatic-api.mdx (1)

163-163: LGTM! Clear documentation of the new gitHooks option.

The documentation clearly describes the new gitHooks field with its allowed values, following the established pattern for other CreateInput fields.

apps/cli/test/addons.test.ts (1)

7-7: LGTM! Test updates align with the Git hooks refactoring.

The removal of "husky" from the universalAddons and multiple addons test cases correctly reflects the architectural change where Husky is now part of the dedicated gitHooks feature rather than an addon.

Also applies to: 178-178

apps/cli/src/utils/display-config.ts (1)

46-48: LGTM! Consistent implementation for displaying gitHooks.

The implementation follows the established pattern used for other configuration options, with proper undefined checking and String() conversion.

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

28-29: LGTM! Clean integration of GitHooks into the public API.

The GitHooks type and schema are properly imported, integrated into the input schema as an optional field, and exported for programmatic usage. The implementation follows the established pattern used for other CLI options.

Also applies to: 90-90, 256-256

apps/cli/test/test-utils.ts (1)

7-7: LGTM! Appropriate default value for test utilities.

The addition of gitHooks: "none" to coreStackDefaults ensures tests have a sensible default value when gitHooks is not explicitly specified, preventing test failures while maintaining consistency with the new Git hooks feature.

Also applies to: 113-113

apps/cli/test/benchmark.test.ts (1)

430-431: LGTM! Correctly demonstrates the Git hooks refactoring.

The change from addons: ["turborepo", "biome", "husky"] to addons: ["turborepo", "biome"] with the addition of gitHooks: "husky" clearly demonstrates the architectural change where Husky is now configured through the dedicated gitHooks option rather than as an addon.

apps/web/src/lib/stack-utils.ts (2)

104-116: LGTM! Husky correctly removed from addons filter.

The removal of "husky" from the allowed addons filter list (it's no longer included) is consistent with the refactoring where Husky is now configured through the gitHooks option instead.


96-96: Verify that stack.gitHooks is always defined.

The template literal --git-hooks ${stack.gitHooks} assumes stack.gitHooks is always defined. If it can be undefined, this would generate --git-hooks undefined in the command string. Verify that StackState type always provides a default value for gitHooks or add a fallback value (e.g., ${stack.gitHooks ?? ''}).

apps/cli/test/backend-runtime.test.ts (1)

40-40: LGTM!

The addition of gitHooks: "none" to the test configuration is consistent with the new Git Hooks feature being introduced across the CLI.

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

53-53: LGTM!

The gitHooks field assignment follows the established pattern with proper fallback precedence: input → detected config → default value.

apps/web/src/lib/stack-url-state.client.ts (1)

35-37: LGTM!

The gitHooks parser implementation is consistent with other string enum parsers in the file, properly using getValidIds and defaulting to DEFAULT_STACK.gitHooks.

apps/cli/src/helpers/core/template-manager.ts (1)

599-610: LGTM!

The setupGitHooksTemplate function follows the established pattern of other template setup functions in this file, including:

  • Early returns for "none" and ultracite scenarios
  • Path existence verification before copying
  • Standard async function declaration per coding guidelines
apps/cli/src/helpers/core/detect-project-config.ts (1)

26-26: LGTM!

The addition of gitHooks: btsConfig.gitHooks is consistent with the pattern used for all other config fields in the detected config object.

apps/web/content/docs/index.mdx (1)

313-314: LGTM!

The documentation correctly reflects the refactoring of Git Hooks into a dedicated configuration option. Moving Husky from addons to the --hooks flag aligns with the PR objectives and provides better separation of concerns.

apps/web/content/docs/cli/index.mdx (1)

30-30: LGTM!

The --git-hooks option documentation is clear, well-positioned after the Git initialization option, and consistent with the format used for other CLI flags.

apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs (1)

1-12: The Lefthook placeholder syntax {staged_files} is correct and matches official documentation. No changes needed. The template properly uses this syntax for both biome and oxlint commands.

Likely an incorrect or invalid review comment.

apps/cli/test/integration.test.ts (2)

38-39: LGTM! Test correctly uses new gitHooks field.

The migration of Husky from addons to the dedicated gitHooks field aligns with the PR's architectural change.

Consider adding a test case with gitHooks: "lefthook" to ensure coverage of the newly introduced option.


186-187: Consistent gitHooks migration across test cases.

All test configurations correctly separate Husky into the gitHooks field while keeping other addons in addons array.

Also applies to: 273-274, 472-473

apps/cli/src/prompts/config-prompts.ts (2)

113-113: LGTM! gitHooks prompt integration follows established patterns.

The gitHooks prompt is correctly wired into the config group without dependencies, which aligns with the PR behavior notes that git hooks selection is independent of other choices.


56-56: Type and return value properly extended.

The PromptGroupResults type and returned configuration object are correctly updated to include gitHooks.

Also applies to: 141-141

apps/cli/src/utils/config-processing.ts (1)

90-92: LGTM! Flag processing follows established pattern.

The gitHooks flag processing mirrors the existing approach for other single-value options like api, backend, and database.

apps/web/src/lib/types.ts (1)

15-15: LGTM! TechCategory type correctly extended.

The gitHooks category is appropriately added to the union type, enabling type-safe handling of git hooks in the web interface.

apps/web/src/lib/stack-url-state.ts (1)

49-51: LGTM! Server-side parser correctly implemented.

The gitHooks parser follows the established pattern used for packageManager and other enum fields, with proper validation via getValidIds and appropriate defaulting.

apps/cli/src/utils/bts-config.ts (1)

27-27: LGTM! BTS config correctly extended with gitHooks.

The gitHooks property is properly added to both the internal config object and the serialized output, ensuring the configuration is persisted in bts.jsonc.

Also applies to: 48-48

apps/web/content/docs/cli/options.mdx (2)

239-253: LGTM! Clear documentation for the new Git Hooks feature.

The new Git Hooks section provides clear documentation for the --git-hooks option with appropriate examples. The default value of none is clearly stated.


273-273: LGTM! Addons example correctly updated.

The example command correctly reflects that Husky has been moved from addons to the dedicated Git Hooks option.

apps/web/content/docs/project-structure.mdx (1)

257-258: LGTM! Configuration schema correctly updated.

The Better-T-Stack configuration schema accurately reflects the changes:

  • Husky removed from addons list
  • New hooks field added with appropriate values
apps/cli/src/helpers/core/create-project.ts (3)

15-15: LGTM! Imports correctly added.

The new Git Hooks setup imports are properly added and follow the existing pattern for other setup features.

Also applies to: 34-34


64-64: LGTM! Template setup correctly positioned.

The Git Hooks template setup is appropriately placed after addons template setup, maintaining consistency with the project scaffolding flow.


88-90: LGTM! Git Hooks setup logic is correct.

The conditional setup correctly checks for non-"none" gitHooks values before invoking the setup function, following the same pattern as auth and payments setup.

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

63-63: LGTM! Ultracite setup call correctly simplified.

The setupUltracite call now passes only the config parameter, correctly reflecting the refactored function signature where Git Hooks logic is handled within the config itself rather than as a separate boolean flag.

apps/cli/test/git-hooks.test.ts (1)

5-212: LGTM! Comprehensive test coverage for Git Hooks.

The test suite provides excellent coverage:

  • Individual git hook options (lefthook, husky, none)
  • Linter integrations (biome, oxlint)
  • Multiple addon combinations
  • Default behavior validation

Once the import issue is fixed, these tests will properly validate the Git Hooks functionality.

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

133-134: LGTM! Function signature correctly refactored.

The function signature has been properly simplified to remove the hasHusky boolean parameter in favor of extracting gitHooks directly from the config. This is a cleaner design that allows Ultracite to support both Lefthook and Husky.


200-202: LGTM! Integration logic correctly updated.

The logic now correctly checks gitHooks !== "none" to determine whether to enable Git Hooks integration, replacing the previous boolean flag approach. This allows Ultracite to support multiple Git Hooks managers.


218-223: LGTM! Dependency installation correctly updated.

The dependency installation logic correctly:

  • Guards installation with gitHooks !== "none"
  • Uses the gitHooks value directly as the package name (which is valid since both "husky" and "lefthook" are real package names)
  • Installs "lint-staged" alongside the selected Git Hooks manager
apps/cli/README.md (3)

43-45: LGTM! Features table correctly updated.

The features table has been properly updated:

  • New Git Hooks row added with Lefthook, Husky, and None options
  • Husky removed from the Addons row

This clearly communicates that Git Hooks are now a separate feature category.


63-63: LGTM! CLI usage documentation updated.

The --git-hooks option is properly documented in the usage section with clear parameter descriptions.


197-197: LGTM! Compatibility note correctly updated.

The compatibility note for addons "none" has been updated to reflect that Husky is no longer part of the addons list.

apps/cli/src/types.ts (5)

88-89: LGTM! Git Hooks schema properly defined.

The GitHooksSchema and GitHooks type are correctly defined using Zod's enum with appropriate values ("husky", "lefthook", "none") and a clear description.


150-150: LGTM! CreateInput type correctly extended.

The gitHooks field is properly added as an optional property to CreateInput, following the same pattern as other optional configuration fields.


160-160: LGTM! AddInput type correctly extended.

The gitHooks field is properly added as an optional property to AddInput, allowing Git Hooks to be configured during the add command.


187-187: LGTM! ProjectConfig interface correctly extended.

The gitHooks field is properly added as a required property to ProjectConfig, ensuring that all resolved project configurations include a Git Hooks value (even if it's "none").


207-207: LGTM! BetterTStackConfig interface correctly extended.

The gitHooks field is properly added to BetterTStackConfig, ensuring that the persisted configuration includes the Git Hooks setting.

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

472-476: LGTM!

The git hooks feature integration is clean. The optional parameter handling and name mapping logic correctly handle both undefined and "none" cases, following the existing pattern used for other features.

apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1)

8-16: LGTM!

The skip logic correctly handles the ultracite case (where ultracite manages its own hooks) and the "none" case. The linter detection logic properly checks addons before delegating to the appropriate setup function.

apps/web/src/lib/constant.ts (3)

472-497: LGTM!

The gitHooks category is well-structured with appropriate options (lefthook, husky, none). The default is correctly set to none for the category, matching the conservative approach of not imposing git hooks by default.


752-752: LGTM!

The gitHooks field is properly added to the StackState type, maintaining consistency with the type alias pattern used throughout the file.


646-646: Verify: Preset templates all default to lefthook.

All preset templates now include gitHooks: "lefthook". This seems intentional as Lefthook is positioned as the preferred option, but it differs from DEFAULT_STACK which uses "none". Confirm this is the desired behavior for preset templates.

Also applies to: 673-673, 700-701, 727-727

@therealsamyak therealsamyak changed the title feat: add lefthook; refactor out Git Hooks to their own section feat: Add lefthook; refactor out Git hooks to their own section Dec 7, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/cli/test/backend-runtime.test.ts (1)

40-40: Consider adding gitHooks: "none" to other test configurations for consistency.

The explicit gitHooks: "none" is correctly added here. However, other test configurations in this file (e.g., invalid combinations, constraint tests) don't explicitly set gitHooks. While the test utilities likely default to "none", explicitly setting it throughout would improve consistency and make the test behavior more predictable.

apps/cli/test/git-hooks.test.ts (1)

160-200: Consider using describe blocks to group related tests.

The tests are well-structured, but using describe blocks (e.g., "Lefthook Linter Integration", "Husky Integration", "Hooks with Addons") would improve readability and match the organization style in other test files like integration.test.ts.

+import { test, describe } from "bun:test";
-import { test } from "bun:test";
 import type { GitHooks } from "../src/types";
 import { runTRPCTest, expectSuccess } from "./test-utils";

 const gitHookOptions = ["husky", "lefthook", "none"] as GitHooks[];

+describe("Git Hooks Configurations", () => {
   for (const gitHook of gitHookOptions) {
-    test(`Git Hooks Configurations - should work with ${gitHook} git hooks`, async () => {
+    test(`should work with ${gitHook} git hooks`, async () => {
       // ... test body
     });
   }
+});
apps/web/content/docs/project-structure.mdx (1)

245-266: Clarify that hooks maps to the Git hooks manager / --git-hooks option

The new "hooks": "<lefthook|husky|none>" field looks correct, but it might help readers if the surrounding text briefly calls out that this controls the Git hooks manager and corresponds to the --git-hooks CLI flag, to avoid confusion with other kinds of “hooks”.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f69ff1f and bb93a72.

📒 Files selected for processing (41)
  • README.md (1 hunks)
  • apps/cli/README.md (3 hunks)
  • apps/cli/src/constants.ts (2 hunks)
  • apps/cli/src/helpers/addons/addons-setup.ts (1 hunks)
  • apps/cli/src/helpers/addons/ultracite-setup.ts (3 hunks)
  • apps/cli/src/helpers/core/add-addons.ts (1 hunks)
  • apps/cli/src/helpers/core/command-handlers.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (4 hunks)
  • apps/cli/src/helpers/core/create-readme.ts (5 hunks)
  • apps/cli/src/helpers/core/detect-project-config.ts (1 hunks)
  • apps/cli/src/helpers/core/post-installation.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1 hunks)
  • apps/cli/src/index.ts (3 hunks)
  • apps/cli/src/prompts/addons.ts (2 hunks)
  • apps/cli/src/prompts/config-prompts.ts (5 hunks)
  • apps/cli/src/prompts/git-hooks.ts (1 hunks)
  • apps/cli/src/types.ts (5 hunks)
  • apps/cli/src/utils/bts-config.ts (2 hunks)
  • apps/cli/src/utils/config-processing.ts (2 hunks)
  • apps/cli/src/utils/display-config.ts (1 hunks)
  • apps/cli/src/validation.ts (1 hunks)
  • apps/cli/templates/addons/ruler/.ruler/bts.md.hbs (1 hunks)
  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs (1 hunks)
  • apps/cli/test/addons.test.ts (2 hunks)
  • apps/cli/test/backend-runtime.test.ts (1 hunks)
  • apps/cli/test/benchmark.test.ts (1 hunks)
  • apps/cli/test/git-hooks.test.ts (1 hunks)
  • apps/cli/test/integration.test.ts (4 hunks)
  • apps/cli/test/test-utils.ts (2 hunks)
  • apps/web/content/docs/cli/index.mdx (1 hunks)
  • apps/web/content/docs/cli/options.mdx (2 hunks)
  • apps/web/content/docs/cli/programmatic-api.mdx (1 hunks)
  • apps/web/content/docs/index.mdx (1 hunks)
  • apps/web/content/docs/project-structure.mdx (1 hunks)
  • apps/web/src/lib/constant.ts (9 hunks)
  • apps/web/src/lib/stack-url-keys.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.client.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.ts (1 hunks)
  • apps/web/src/lib/stack-utils.ts (2 hunks)
  • apps/web/src/lib/types.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/cli/templates/addons/ruler/.ruler/bts.md.hbs
🚧 Files skipped from review as they are similar to previous changes (23)
  • apps/web/src/lib/stack-url-keys.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/src/utils/config-processing.ts
  • apps/cli/src/constants.ts
  • apps/web/content/docs/cli/index.mdx
  • apps/cli/README.md
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/web/content/docs/cli/programmatic-api.mdx
  • README.md
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/utils/display-config.ts
  • apps/cli/src/types.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/index.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/cli/src/helpers/core/create-project.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/test/addons.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/constant.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/web/src/lib/types.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/test/addons.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/constant.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/web/src/lib/types.ts
**/*.{ts,tsx,js,jsx}

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

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

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/constant.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/web/src/lib/types.ts
**/*.test.{ts,tsx,js,jsx}

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

**/*.test.{ts,tsx,js,jsx}: Use bun test instead of jest or vitest for running tests
Use bun:test module with test and expect functions for writing tests

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
**/*.{ts,tsx,js,jsx,css}

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

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

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/constant.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/web/src/lib/types.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/test/addons.test.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/constant.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/web/src/lib/types.ts
🧠 Learnings (4)
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
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/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
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/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:14.703Z
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.703Z
Learning: Applies to convex/**/*.ts : Use the api object from convex/_generated/api.ts to call public functions registered with query, mutation, or action

Applied to files:

  • apps/cli/src/helpers/core/create-readme.ts
🧬 Code graph analysis (5)
apps/cli/src/helpers/core/template-manager.ts (2)
apps/cli/src/types.ts (1)
  • ProjectConfig (167-188)
apps/cli/src/constants.ts (1)
  • PKG_ROOT (7-7)
apps/cli/src/helpers/addons/ultracite-setup.ts (2)
apps/cli/src/types.ts (1)
  • ProjectConfig (167-188)
apps/cli/src/utils/add-package-deps.ts (1)
  • addPackageDependency (6-57)
apps/web/src/lib/stack-url-state.client.ts (1)
apps/web/src/lib/constant.ts (2)
  • StackState (740-761)
  • DEFAULT_STACK (763-784)
apps/cli/src/helpers/core/create-readme.ts (2)
apps/cli/src/index.ts (1)
  • GitHooks (256-256)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
apps/cli/src/helpers/addons/addons-setup.ts (1)
apps/cli/src/helpers/addons/ultracite-setup.ts (1)
  • setupUltracite (133-232)
🔇 Additional comments (25)
apps/cli/src/prompts/addons.ts (1)

46-66: LGTM! Clean migration of Husky out of addons.

The removal of Husky from the addons switch case and ADDON_GROUPS.Other is consistent with the PR's objective to move Git hooks into their own configuration surface.

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

26-26: LGTM! Correct propagation of gitHooks field.

The gitHooks field is properly extracted from the BTS config and included in the returned project configuration, consistent with other config fields.

apps/cli/src/helpers/core/template-manager.ts (1)

599-610: LGTM! Well-structured Git hooks template setup.

The function correctly:

  • Guards against invalid states (none, missing gitHooks)
  • Skips when Ultracite is handling hooks (per PR behavior notes)
  • Follows the established template setup pattern
  • Uses standard function declaration syntax as per coding guidelines
apps/web/src/lib/types.ts (1)

15-15: LGTM! Correct union type extension.

The addition of "gitHooks" to TechCategory properly extends the type to support the new Git hooks configuration category.

apps/cli/src/utils/bts-config.ts (1)

27-48: LGTM! Proper gitHooks config persistence.

The gitHooks field is correctly included in both the runtime config object and the serialized baseContent, ensuring it persists in bts.jsonc and remains available for downstream operations.

apps/cli/src/helpers/core/create-readme.ts (3)

11-11: LGTM! Correct type import.

The GitHooks type import enables type-safe handling of the gitHooks parameter in README generation.


42-70: LGTM! Proper gitHooks propagation.

The gitHooks field is correctly destructured from options and passed through to generateFeaturesList, maintaining consistency with how other config fields are handled.


353-476: LGTM! Well-implemented Git hooks feature rendering.

The implementation correctly:

  • Uses an optional parameter since gitHooks may be "none"
  • Guards against undefined and "none" values before rendering
  • Maps gitHooks values to appropriate display names
  • Adds the feature to the list in a consistent format
apps/web/content/docs/index.mdx (1)

313-314: LGTM! Documentation correctly updated.

The docs properly reflect the migration of Husky from addons to the new --hooks flag, with accurate values (lefthook, husky, none) documented for users.

apps/cli/test/addons.test.ts (2)

7-7: LGTM! Test correctly updated for Husky migration.

Removing "husky" from the universalAddons array aligns with the PR's migration of Husky from addons to the gitHooks configuration.


178-178: LGTM! Multiple addons test correctly updated.

The test array properly excludes "husky" while still validating that multiple compatible addons can be used together.

apps/cli/test/integration.test.ts (4)

38-39: LGTM!

The migration of husky from the addons array to a dedicated gitHooks: "husky" field is correctly implemented. This aligns with the PR's objective to refactor Git hooks into their own section.


186-187: LGTM!

Consistent application of the gitHooks field for the MongoDB + Mongoose test configuration.


273-274: LGTM!

Frontend-only Nuxt test configuration correctly updated with gitHooks field.


472-473: LGTM!

Maximum complexity test configuration correctly updated to use gitHooks instead of husky in addons.

apps/web/content/docs/cli/options.mdx (2)

239-253: LGTM!

The new Git Hooks section is well-documented with clear descriptions for each option (lefthook, husky, none) and helpful usage examples. The placement after Authentication and before Addons is logical.


273-273: LGTM!

The addons example correctly excludes husky, which is now documented in the Git Hooks section.

apps/web/src/lib/stack-url-state.client.ts (1)

35-37: LGTM!

The gitHooks parser follows the established pattern used by other enum parsers in this file. It correctly uses parseAsStringEnum with valid IDs from TECH_OPTIONS["gitHooks"] and defaults to DEFAULT_STACK.gitHooks ("none").

apps/cli/test/git-hooks.test.ts (4)

1-3: LGTM!

Correct usage of bun:test per coding guidelines. The imports are appropriate for the test file.


5-28: LGTM!

Good use of a loop to test all gitHook options, reducing code duplication while ensuring coverage for husky, lefthook, and none configurations.


30-93: LGTM!

Comprehensive Lefthook integration tests covering biome, oxlint, and standalone scenarios. Test configurations are complete and follow established patterns.


95-158: LGTM!

Comprehensive Husky integration tests mirroring the Lefthook tests for consistency. Good coverage of biome, oxlint, and standalone scenarios.

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

59-68: Ultracite setup now correctly forwards full ProjectConfig (including gitHooks)

Switching to setupUltracite(config) keeps the Biome/Ultracite branching intact and correctly passes gitHooks and other fields through the config object; the control flow for ultracite vs biome remains sound.

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

133-135: gitHooks-based Ultracite integration and dependency wiring look consistent

Using config.gitHooks to gate --integrations <gitHooks> lint-staged and to install [gitHooks, "lint-staged"] only when gitHooks !== "none" matches the intended behavior and cleanly replaces the earlier hasHusky flag.

Also applies to: 200-202, 218-221

apps/web/src/lib/constant.ts (1)

472-497: gitHooks option and defaults are wired consistently across web constants and presets

The new gitHooks tech category, its default of "none", the preset stacks setting "lefthook" where desired, and the StackState/DEFAULT_STACK updates all align and should integrate cleanly with the rest of the stack/state logic.

Also applies to: 646-647, 673-674, 700-703, 727-728, 752-752, 775-775

@therealsamyak
Copy link
Author

@AmanVarshney01 this is ready to review when you are!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
apps/web/content/docs/cli/programmatic-api.mdx (1)

163-163: Improve inline comment to describe field purpose, not just values.

The comment lists allowed values but doesn't describe what the field does. Compare with the git field above (line 162: "Initialize git repo"), which is more informative. Consider updating the comment to explain the purpose.

- gitHooks?: GitHooks;             // "lefthook" | "husky" | "none"
+ gitHooks?: GitHooks;             // Git hooks manager: "lefthook" | "husky" | "none"

Alternatively, if you want to keep it even more concise to match the union-type pattern, just ensure consistency:

- gitHooks?: GitHooks;             // "lefthook" | "husky" | "none"
+ gitHooks?: GitHooks;             // Git hooks manager ("lefthook" | "husky" | "none")
apps/web/src/lib/stack-url-keys.ts (1)

17-17: Consider using an abbreviated URL key for consistency.

Most URL keys use abbreviated forms (e.g., pm, add, ex, wd). Consider using gh instead of gitHooks to keep URLs shorter and consistent with the abbreviated pattern:

-  gitHooks: "gitHooks",
+  gitHooks: "gh",

That said, keys like api, git, and yolo also use full names, so the current approach is acceptable.

apps/web/src/lib/constant.ts (1)

540-541: Minor: Remove trailing empty line.

This appears to be leftover formatting from removing Husky from addons. Consider removing the extra blank line for cleaner formatting.

apps/cli/test/addons.test.ts (1)

7-30: Addon tests correctly drop Husky; consider deriving lists from shared config

Updating universalAddons, the “multiple compatible addons” config, and testableAddons to exclude "husky" matches the new separation between addons and gitHooks. To reduce future drift, you could derive these arrays from AddonsSchema.options (filtering out prompt‑only addons) instead of maintaining the string lists by hand, but that’s optional.

Also applies to: 174-195, 283-323

apps/cli/test/integration.test.ts (1)

28-45: Integration tests now exercise Husky via gitHooks; add a Lefthook case for full coverage

Switching Husky from addons to gitHooks: "husky" in these scenarios keeps real‑world coverage aligned with the new API shape. To fully exercise the new --git-hooks surface, it would be worth adding at least one analogous integration test using gitHooks: "lefthook" (with Biome/Oxlint enabled) so both hook managers are covered end‑to‑end.

Also applies to: 176-193, 263-281, 461-479

apps/cli/test/git-hooks.test.ts (2)

1-28: Parameterized gitHooks tests are well-structured

The shared gitHookOptions array plus the looped test covers all three allowed git hooks values with a single, readable pattern, and each run uses a distinct projectName, so there’s no cross-test directory clash. Just keep in mind that if new git hooks modes are ever added to the config, this array will need updating to keep coverage aligned, but as written it’s correct and maintainable.


30-200: Comprehensive scenario coverage; minor duplication only

These tests thoroughly exercise git hooks with and without linters (Biome/Oxlint), both managers (lefthook/husky), multiple addons, and the implicit default case where gitHooks is omitted. The configurations and projectName values are consistent and should give good confidence that CLI scaffolding works across combinations. If this suite grows further, consider extracting a small helper to build the common config shape (frontend/backend/runtime/db/auth/api flags) to reduce repetition, but that’s optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bb93a72 and fb1e620.

📒 Files selected for processing (41)
  • README.md (1 hunks)
  • apps/cli/README.md (3 hunks)
  • apps/cli/src/constants.ts (2 hunks)
  • apps/cli/src/helpers/addons/addons-setup.ts (1 hunks)
  • apps/cli/src/helpers/addons/ultracite-setup.ts (3 hunks)
  • apps/cli/src/helpers/core/add-addons.ts (1 hunks)
  • apps/cli/src/helpers/core/command-handlers.ts (1 hunks)
  • apps/cli/src/helpers/core/create-project.ts (4 hunks)
  • apps/cli/src/helpers/core/create-readme.ts (5 hunks)
  • apps/cli/src/helpers/core/detect-project-config.ts (1 hunks)
  • apps/cli/src/helpers/core/post-installation.ts (2 hunks)
  • apps/cli/src/helpers/core/template-manager.ts (1 hunks)
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts (1 hunks)
  • apps/cli/src/index.ts (3 hunks)
  • apps/cli/src/prompts/addons.ts (2 hunks)
  • apps/cli/src/prompts/config-prompts.ts (5 hunks)
  • apps/cli/src/prompts/git-hooks.ts (1 hunks)
  • apps/cli/src/types.ts (5 hunks)
  • apps/cli/src/utils/bts-config.ts (2 hunks)
  • apps/cli/src/utils/config-processing.ts (2 hunks)
  • apps/cli/src/utils/display-config.ts (1 hunks)
  • apps/cli/src/validation.ts (1 hunks)
  • apps/cli/templates/addons/ruler/.ruler/bts.md.hbs (1 hunks)
  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs (1 hunks)
  • apps/cli/test/addons.test.ts (2 hunks)
  • apps/cli/test/backend-runtime.test.ts (1 hunks)
  • apps/cli/test/benchmark.test.ts (1 hunks)
  • apps/cli/test/git-hooks.test.ts (1 hunks)
  • apps/cli/test/integration.test.ts (4 hunks)
  • apps/cli/test/test-utils.ts (2 hunks)
  • apps/web/content/docs/cli/index.mdx (1 hunks)
  • apps/web/content/docs/cli/options.mdx (2 hunks)
  • apps/web/content/docs/cli/programmatic-api.mdx (1 hunks)
  • apps/web/content/docs/index.mdx (1 hunks)
  • apps/web/content/docs/project-structure.mdx (1 hunks)
  • apps/web/src/lib/constant.ts (9 hunks)
  • apps/web/src/lib/stack-url-keys.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.client.ts (1 hunks)
  • apps/web/src/lib/stack-url-state.ts (1 hunks)
  • apps/web/src/lib/stack-utils.ts (2 hunks)
  • apps/web/src/lib/types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (30)
  • apps/web/src/lib/stack-url-state.client.ts
  • apps/cli/templates/addons/ruler/.ruler/bts.md.hbs
  • apps/cli/src/constants.ts
  • apps/cli/src/helpers/core/template-manager.ts
  • apps/cli/src/helpers/core/detect-project-config.ts
  • apps/cli/src/index.ts
  • apps/web/content/docs/project-structure.mdx
  • apps/cli/src/utils/display-config.ts
  • apps/cli/src/prompts/git-hooks.ts
  • apps/cli/test/backend-runtime.test.ts
  • apps/cli/src/prompts/config-prompts.ts
  • apps/cli/src/helpers/core/command-handlers.ts
  • apps/web/src/lib/stack-utils.ts
  • apps/web/content/docs/cli/options.mdx
  • apps/cli/src/helpers/addons/ultracite-setup.ts
  • apps/cli/src/validation.ts
  • apps/cli/src/helpers/core/post-installation.ts
  • apps/web/src/lib/stack-url-state.ts
  • apps/cli/src/helpers/git-hooks/git-hooks-setup.ts
  • apps/cli/src/helpers/core/add-addons.ts
  • apps/cli/test/benchmark.test.ts
  • apps/cli/src/utils/bts-config.ts
  • apps/cli/templates/git-hooks/lefthook/lefthook.yml.hbs
  • apps/web/content/docs/cli/index.mdx
  • apps/cli/src/utils/config-processing.ts
  • apps/web/content/docs/index.mdx
  • apps/cli/src/types.ts
  • apps/cli/test/test-utils.ts
  • apps/cli/src/helpers/core/create-project.ts
  • apps/web/src/lib/types.ts
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/constant.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/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/constant.ts
**/*.{ts,tsx,js,jsx}

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

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

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/constant.ts
**/*.test.{ts,tsx,js,jsx}

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

**/*.test.{ts,tsx,js,jsx}: Use bun test instead of jest or vitest for running tests
Use bun:test module with test and expect functions for writing tests

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
**/*.{ts,tsx,js,jsx,css}

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

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

Files:

  • apps/cli/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/constant.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/test/addons.test.ts
  • apps/cli/test/integration.test.ts
  • apps/cli/test/git-hooks.test.ts
  • apps/cli/src/prompts/addons.ts
  • apps/cli/src/helpers/addons/addons-setup.ts
  • apps/cli/src/helpers/core/create-readme.ts
  • apps/web/src/lib/stack-url-keys.ts
  • apps/web/src/lib/constant.ts
🧠 Learnings (4)
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
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/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests

Applied to files:

  • apps/cli/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:26.410Z
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.410Z
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/test/git-hooks.test.ts
📚 Learning: 2025-12-03T07:48:14.703Z
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.703Z
Learning: Applies to convex/**/*.ts : Use the api object from convex/_generated/api.ts to call public functions registered with query, mutation, or action

Applied to files:

  • apps/cli/src/helpers/core/create-readme.ts
🧬 Code graph analysis (3)
apps/cli/test/git-hooks.test.ts (2)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
apps/cli/test/test-utils.ts (2)
  • runTRPCTest (58-161)
  • expectSuccess (163-173)
apps/cli/src/helpers/addons/addons-setup.ts (1)
apps/cli/src/helpers/addons/ultracite-setup.ts (1)
  • setupUltracite (133-232)
apps/cli/src/helpers/core/create-readme.ts (2)
apps/cli/src/index.ts (1)
  • GitHooks (256-256)
apps/cli/src/types.ts (1)
  • GitHooks (89-89)
🔇 Additional comments (12)
README.md (1)

47-48: Documentation properly reflects Git Hooks as distinct feature.

The changes cleanly move Husky from Addons into the new Git Hooks section while maintaining the comprehensive addon list. Formatting and feature presentation are consistent with the rest of the README.

apps/cli/README.md (4)

43-43: Git Hooks table row properly integrated.

The new table entry follows the established format, lists correct options (Lefthook, Husky, None), and fits naturally within the Features documentation structure.


45-45: Addons section correctly updated.

Husky has been cleanly removed from the Addons row. The remaining addons are properly formatted and consistent with the PR's refactoring objective.


62-63: CLI options properly documented.

The new --git-hooks <type> option is correctly documented with appropriate values and formatting consistent with other CLI flags. The addons option no longer references Husky.


197-197: Compatibility notes updated consistently.

The Addons 'none' compatibility note has been properly updated to remove reference to Husky, maintaining internal consistency with the broader refactoring.

apps/web/src/lib/constant.ts (3)

472-497: LGTM!

The new gitHooks category is well-structured with appropriate options (lefthook, husky, none) and sensible defaults. The configuration follows the established pattern of other tech options.


646-647: LGTM!

The gitHooks: "lefthook" addition to preset templates is consistent across all presets (mern, pern, t3, uniwind), aligning with the PR's intent to promote Lefthook as the recommended Git hooks manager.


752-752: LGTM!

The gitHooks field is correctly added to StackState type with an appropriate default of "none" in DEFAULT_STACK, allowing users to opt-in to Git hooks management.

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

63-63: LGTM: Clean refactoring that improves separation of concerns.

The simplified call to setupUltracite(config) correctly aligns with the new architecture where Git hooks configuration is managed through the config.gitHooks field rather than a separate boolean parameter. This refactoring moves Git hooks setup logic to a dedicated module, improving maintainability and reducing coupling in the addons setup flow.

apps/cli/src/prompts/addons.ts (1)

17-58: Husky removal from addon display/groups looks consistent with new Git Hooks model

The switch in getAddonDisplay and ADDON_GROUPS.Other now exclude "husky", so Husky will no longer appear as an addon option, which matches the move to a dedicated gitHooks field. As long as "husky" has also been removed from AddonsSchema.options, this prompt logic remains consistent and won’t ever hit the generic default branch for Husky.

Also applies to: 63-67

apps/cli/src/helpers/core/create-readme.ts (2)

28-43: gitHooks plumbing into README generation is consistent

Destructuring gitHooks from options and threading it into generateFeaturesList cleanly connects the new config field to README output without changing other behavior. This keeps README content in sync with the project’s git hooks choice while remaining backward compatible when gitHooks is absent.

Also applies to: 70-70


344-354: Git hooks feature entry in Features list behaves as expected

Extending generateFeaturesList with an optional gitHooks parameter and appending a single bullet when it’s set to something other than "none" is straightforward and matches the current allowed values (labeling "husky" vs "lefthook"). This keeps the Features section accurate without clutter when no hooks manager is selected.

Also applies to: 472-476

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant