Skip to content

feat(init): add init command with framework scaffolding and agent prompts - #38

Merged
rafa-thayto merged 35 commits into
mainfrom
rafa-thayto/add-init-command
Mar 24, 2026
Merged

feat(init): add init command with framework scaffolding and agent prompts#38
rafa-thayto merged 35 commits into
mainfrom
rafa-thayto/add-init-command

Conversation

@rafa-thayto

@rafa-thayto rafa-thayto commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Rewrite clerk init to detect the project's framework, install the Clerk SDK, pull env vars, and scaffold framework-specific boilerplate (middleware, providers, auth pages)
  • Support 10 frameworks for detection (Next.js, Astro, Nuxt, TanStack Start, React Router, Vue, Expo, React, Express, Fastify) and 8 for scaffolding
  • Fix incorrect SDK package names (@clerk/clerk-react@clerk/react, @clerk/tanstack-start@clerk/tanstack-react-start) and remove standalone Vite detection
  • Add pre-scaffold auth library detection (NextAuth, Auth0, Supabase, Firebase, Passport, Better Auth, Kinde) with migration docs
  • Add post-scaffold code scanning for hardcoded keys and leftover auth imports
  • All scaffolding is idempotent — existing Clerk setup is detected and skipped, existing middleware is composed rather than overwritten
  • Skip login/link when user is already authenticated and linked
  • Restructure agent mode prompts into individual markdown templates matching the clerk-docs format (sections, ALWAYS/NEVER rules, deprecated patterns, verification checklists, after-setup guidance)
  • Add agent prompts for Expo, Express, and Fastify frameworks

Agent prompts

Prompts for clerk init --mode agent now live as individual .md files in src/commands/init/prompts/, using {{PLACEHOLDER}} interpolation for dynamic context (package manager, file extensions, paths). Each prompt follows the clerk-docs structure:

  • One-line summary → Install → Copy-paste code blocks → Rules (ALWAYS/NEVER) → Deprecated patterns → Verify checklist → After Setup
Template Framework
nextjs-app-router.md Next.js App Router (with Keyless Mode)
nextjs-pages-router.md Next.js Pages Router (with Keyless Mode)
react.md React / Vite
react-router.md React Router
nuxt.md Nuxt
tanstack-start.md TanStack Start
astro.md Astro
vue.md Vue
expo.md Expo (React Native)
express.md Express
fastify.md Fastify
generic.md Fallback (no framework detected)
generic-fallback.md Fallback (framework detected, no specific template)

Scaffolding support

Framework Middleware Provider Auth pages
Next.js (App Router) clerkMiddleware with route protection ClerkProvider in layout sign-in/sign-up catch-all pages
Next.js (Pages Router) Same as App Router ClerkProvider in _app sign-in/sign-up catch-all pages
React Router clerkMiddleware + rootAuthLoader ClerkProvider with loaderData sign-in/sign-up routes
TanStack Start clerkMiddleware in requestMiddleware ClerkProvider in root sign-in/sign-up routes
Nuxt Auto-configured via module Auto-configured sign-in/sign-up Vue pages
Astro clerkMiddleware with onRequest clerk() integration sign-in/sign-up Astro pages
React / Vite ClerkProvider in entry
Vue clerkPlugin in entry

Test plan

  • bun test — 415 tests pass, 0 failures
  • bun run lint — 0 errors
  • bun run format:check — all files formatted
  • TypeScript checks pass for all init command files
  • Manual test: run clerk init in a fresh Next.js project
  • Manual test: run clerk init in a fresh React (Vite) project
  • Manual test: run clerk init --mode agent to verify prompt output

Summary by CodeRabbit

  • New Features

    • Init command expanded into a multi-mode, agent-aware onboarding flow with preview & confirm and automatic framework-specific scaffolding (Next.js App/Pages, React, Vue, Nuxt, React Router, TanStack Start, Astro, Expo, Express, Fastify)
    • Automatic post-write formatting of generated files and post-scaffold code scanning for potential issues
  • Documentation

    • Added comprehensive, framework-specific setup guides and templated prompts to streamline integration and follow-up instructions

@coderabbitai

coderabbitai Bot commented Mar 18, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR restructures init into a context-driven workflow and adds project detection, enrichment, and scaffold orchestration. New modules include context detection, formatters, scaffold registry, per-framework scaffolders (Next.js app/pages, React/Vite, React Router, Nuxt, TanStack Start, Astro, Vue), Next.js context enrichment and helpers, scanning/issue detection, preview-and-confirm, prompt templates, and many tests. It also exports framework types and utilities, and adds a runtime dependency: magicast at ^0.5.2 in package.json.


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

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

@rafa-thayto rafa-thayto changed the title feat: add init command with framework scaffolding feat(init): add init command with framework scaffolding and agent prompts Mar 18, 2026
@rafa-thayto
rafa-thayto requested review from Railly, brkalow, dmoerner, jfoshee, kylemac and wyattjoh and removed request for brkalow March 18, 2026 14:10
@rafa-thayto
rafa-thayto force-pushed the rafa-thayto/add-init-command branch from 1baab9c to f9bd7ed Compare March 18, 2026 14:11
Comment thread packages/cli-core/src/commands/init/README.md
Comment thread src/commands/init/context.ts Outdated
Comment thread src/commands/init/scaffold.ts Outdated
Comment thread src/commands/init/scaffold.ts Outdated
Comment thread src/commands/init/scan.ts Outdated
Comment thread src/commands/init/frameworks/astro.ts Outdated
Comment thread src/commands/init/frameworks/nextjs-app.ts Outdated
Comment thread src/commands/init/frameworks/nuxt.ts Outdated
Comment thread packages/cli-core/src/commands/init/frameworks/vue.ts
Comment thread packages/cli-core/src/commands/init/prompts/index.ts Outdated
Comment thread packages/cli-core/src/commands/init/format.ts
@rafa-thayto

rafa-thayto commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 20, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

1 similar comment
@coderabbitai

coderabbitai Bot commented Mar 20, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@rafa-thayto
rafa-thayto force-pushed the rafa-thayto/add-init-command branch 2 times, most recently from 32ee86a to 40b2c6a Compare March 20, 2026 20:41
@wyattjoh
wyattjoh self-requested a review March 20, 2026 21:15
@jfoshee

jfoshee commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Is this PR ready for review? I see ongoing changes and it is already about 5000 lines. Is some of this generated code?

@rafa-thayto

Copy link
Copy Markdown
Contributor Author

@jfoshee yeah, it's ready.

It's already about 5,000 lines, with half of it being prompts and the rest scaffolding code

Used by the init command's framework scaffolders to safely add imports
and modify config files without breaking existing code.
- Fix @clerk/clerk-react → @clerk/react
- Fix @clerk/tanstack-start → @clerk/tanstack-react-start
- Remove standalone vite detection (covered by react)
- Reorder priority: scaffoldable frameworks first, then expo, react,
  express, fastify
- Export readDeps for use by init context module
Detects framework, TypeScript, src/ directory convention, package
manager, Next.js router variant, middleware filename, layout path,
and existing Clerk SDK installation.
Add idempotent scaffolders for Next.js (App + Pages Router), React,
React Router, Nuxt, TanStack Start, Astro, and Vue. Each scaffolder
generates framework-appropriate boilerplate (middleware, providers,
auth pages) while preserving existing user code.

Shared helpers handle AST-based import injection (magicast with string
fallback), middleware composition, and auth page creation.
- scan: detect competing auth libraries pre-scaffold and scan for
  hardcoded keys/leftover imports post-scaffold
- format: run Prettier/Biome on generated files
- preview: show planned file changes and confirm before writing
- prompts: framework-specific agent mode prompts with exact code
  snippets and file paths
Replace the minimal init (login + link + install + env pull) with a
full orchestrator that also scaffolds framework boilerplate and scans
for issues. Skips login/link when already authenticated and linked.
- Add Agent Mode section
- Add env var column to framework detection table
- Add Expo, Express, Fastify to detection table
- Document scaffolding actions for all 8 supported frameworks
- Note that Expo/Express/Fastify are detected but not scaffolded
Replace monolithic prompts.ts with individual .md template files per
framework, matching the clerk-docs structured format (sections, rules,
deprecated patterns, verification checklists).

- Move prompts to src/commands/init/prompts/*.md with {{PLACEHOLDER}}
  interpolation
- Add prompts for expo, express, and fastify frameworks
- Merge DOCS_URLS + TEMPLATE_MAP into single FRAMEWORK_PROMPTS record
- Extract shared pmInstallCommand, remove duplicate pmAddCommand
- Fix formatter-escaped underscores (\_app, \_\_root) in template loader
- Add "After Setup" section to all prompts (matching clerk-docs)
…js-context

Move parseNextMajorVersion, detectMiddlewareBasename, detectNextjsVariant,
and detectLayoutPath from context.ts into a dedicated nextjs-context.ts
module. This isolates framework-specific logic behind the enrichContext
hook on FrameworkScaffold rather than coupling it to gatherContext.
Parallelize dirExists calls with Promise.all in both files.
…version check

Replace the Record<string, FrameworkScaffold> keyed map with an array
using satisfies and matches()-based lookup. Add enrichProjectContext()
that delegates to each scaffolder's enrichContext hook. Add minMajorVersion
guard that checks the framework dep version before scaffolding.
Add parseMajorVersion, insertAfterLastImport, wrapBodyWithProvider, and
resolveNextjsMiddlewareBasename to helpers. Use proper skip FileAction
in scaffoldAuthPage and scaffoldNextjsMiddleware. Flatten nested ifs
with early returns and store BunFile reference once. The middleware
fallback now resolves from the actual Next.js version in deps.
…, and minMajorVersion

Each scaffolder now exports dep, matches(), and minMajorVersion. All skip
cases use the proper FileAction skip variant. Flatten nested ifs with
early returns across scaffoldLayout, scaffoldApp, scaffoldMiddleware, and
scaffoldConfig. Use shared wrapBodyWithProvider (nextjs-app, tanstack-start),
insertAfterLastImport (react-router, vue), and extract wrapWithClerkProvider
in react.ts. Store BunFile references to avoid duplicate creation.
… internal types

Remove MAX_FINDINGS so no context is lost. Convert IGNORE_DIRS to a Set
for O(1) lookups. Precompile CODE_SCANS regexes once at module level.
Inline matchesFramework guard. Convert AuthLibraryScan and CodeScan from
exported interfaces to local types since they are not imported elsewhere.
…piled binaries

Use Bun's `import ... with { type: "text" }` to embed markdown prompt
templates at build time. This replaces the runtime readFileSync +
import.meta.dir approach that would break in compiled Bun binaries.
Remove the template cache since imports are already static.
Replace inline if-checks for prettier/biome with a FormatterConfig type
and a FORMATTERS array. The runFormatters loop now iterates the config,
making it trivial to add new formatters.
…version check

Update context tests to call enrichProjectContext separately from
gatherContext and import parseMajorVersion from helpers. Add tests for
scaffold version check (below minimum, meets minimum, Next.js 16 proxy).
Update nextjs-app tests to assert on the skip type instead of skipReason
field. Update scan test to verify all findings are returned without cap.
Add jsxAuthPageContent with type-safe JsxClerkPackage union,
scaffoldConfigFile generic for the find→check→modify pattern,
authComponentName, and inline capitalize. These shared helpers
eliminate duplication across framework scaffolders.
Replace duplicated authRouteContent/nextjsAuthPageContent with
jsxAuthPageContent, replace per-framework scaffoldConfig with
scaffoldConfigFile in astro, nuxt, and react-router. Remove
unused imports and add enableV8Middleware documentation.
Update preview formatting to use switch on discriminated union,
restructure prompts/index.ts with typed template resolution and
variable building, and minor scan.ts cleanup.
Add tests for nextjs-app (middleware composition, provider wrapping,
src/ paths, proxy basename), react-router (root modification, loader
merge), tanstack-start (base dir detection), and scan (no findings cap).
Export FRAMEWORK_MAP and add lookupFramework() to resolve framework
names or aliases (e.g. "tanstack-start" → "@tanstack/react-start")
along with FRAMEWORK_NAMES for validation and display.
Add optional i18nLocaleDir field to ProjectContext for frameworks
that detect locale-based routing directories (e.g. [locale], [lang]).
Split preview logic into previewPlan() (display only) and
previewAndConfirm() (display + prompt) to support --yes mode
without duplicating the plan rendering code.
Add reusable helpers for all framework scaffolders:
- authFileSpecs() factory for sign-in/sign-up file generation
- scaffoldEnvVars() and SIGN_ROUTE_ENV_VARS for env file management
- htmlAuthComponentMarkup() and jsxAuthComponentMarkup() with
  Tailwind/plain CSS variants
- hasTailwindStyles() for style detection
- i18n middleware detection, composition, and routing helpers
  (detectI18nMiddlewareLib, composeWithI18nMiddleware, etc.)
- findFirstDirMatch() for generic directory scanning
Add detectI18nLocaleDir() to identify App Router locale directories
(e.g. [locale], [lang]) by checking for layout files inside dynamic
segments. Populate i18nLocaleDir in enrichNextjsContext() so
scaffolders can place auth pages inside locale-prefixed paths.
Accept optional frameworkOverride parameter in gatherContext() to
skip auto-detection when the user specifies --framework explicitly.
Register --framework <name>, -y/--yes, and --prompt options on the
init command. Wire them through to framework override resolution,
preview-only plan display, and agent prompt output respectively.
Update all six framework scaffolders (Astro, Next.js App/Pages,
Nuxt, React Router, TanStack Start) to use the shared helpers:
- authFileSpecs() factory for sign-in/sign-up generation
- scaffoldEnvVars() for .env file management
- hasTailwindStyles() for consistent style detection
- i18n-aware auth page placement using locale directory detection
- htmlAuthComponentMarkup()/jsxAuthComponentMarkup() for rendering
Add tests for i18n support across frameworks:
- Context: locale directory detection ([locale], [lang]) with
  layout file validation and src/ convention support
- Next.js App Router: i18n auth page placement, composed Clerk +
  next-intl middleware, expression export handling, env var scaffolding
- React Router: ($locale) prefix detection for auth routes
- TanStack Start: {-$locale} directory detection for auth routes
Add --framework, --yes, and --prompt options to init command README
with usage examples. Update root README help output with --verbose
flag documentation.
@rafa-thayto
rafa-thayto force-pushed the rafa-thayto/add-init-command branch from 071d210 to ceeb037 Compare March 24, 2026 02:56

@jfoshee jfoshee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I time-boxed my review due to the size of the PR and youth of this project. I think it's more important to get this into people's hands for testing than this have perfect code design. I did not see any blockers and I do hope people start trying this soon.

The test matrix is already getting kind-of big. I know @wyattjoh was looking at E2E tests. I expect we will want to regularly ensure that the edge version of clerk init works with the edge versions of all create templates for the various frameworks. And, as you know, each framework has variants/options. So, it would be good to start to enumerate all of those cases so we can eventually cover them with automated tests.

I manually tested NextJS and Astro taking the defaults and they worked fine. I expect we will iterate on the output to include things like sign-in buttons / user button, but totally fine to save that for later.

I like the general structure here and presence of unit tests. There are some gaps in testing, so I expect those will be covered in time.

And, I expect we will continue to keep an eye on the code structure and do refactorings as we see the patterns and logical groupings of functions. I noticed we have heuristics for detecting things in the file system, heuristics for detecting things within code text, operations for transforming text, etc.

Thanks for this huge effort, Rafael.

Comment thread packages/cli-core/src/commands/init/frameworks/helpers.ts
Comment thread packages/cli-core/src/commands/init/frameworks/nextjs-app.test.ts Outdated
Comment thread packages/cli-core/src/commands/init/frameworks/nextjs-app.test.ts Outdated
Comment thread packages/cli-core/src/commands/init/index.ts Outdated
Comment thread packages/cli-core/src/commands/init/frameworks/helpers.ts Outdated
Comment thread packages/cli-core/src/commands/init/frameworks/nuxt.ts
Comment thread packages/cli-core/src/commands/init/frameworks/astro.ts
Comment thread packages/cli-core/src/commands/init/frameworks/types.ts
Comment thread packages/cli-core/src/commands/init/prompts/astro.md Outdated
Comment thread packages/cli-core/src/commands/init/prompts/astro.md
- Extract utility helpers from index.ts into heuristics.ts (jfoshee #18)
- Extract text transformations into transformations.ts (jfoshee #19)
- Fix wrapBodyWithProvider whitespace/formatting bug (jfoshee #20)
- Refactor tests to use semantic path lookups instead of positional
  array indexing (jfoshee #13/#17)
- Add doc comment to helpers.ts clarifying shared usage (jfoshee #15)
- Update astro.md NEVER rules to start with "Never" (jfoshee #25)
- Remove section banner comments from init command files
Add test coverage for the 5 framework scaffolders that were missing
tests (jfoshee #21/#22):
- astro.test.ts (10 tests)
- nuxt.test.ts (8 tests)
- vue.test.ts (6 tests)
- react.test.ts (7 tests)
- nextjs-pages.test.ts (10 tests)

All tests use semantic path-based lookups via findAction() helper.
@rafa-thayto
rafa-thayto merged commit 36c36fa into main Mar 24, 2026
3 checks passed
@rafa-thayto
rafa-thayto deleted the rafa-thayto/add-init-command branch March 24, 2026 21:45
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.

4 participants