create-better-t-stack 2.35.5-canary.869063df → 2.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,40 +45,6 @@ Follow the prompts to configure your project or use the `--yes` flag for default
45
45
  | **Examples** | • Todo app<br>• AI Chat interface (using Vercel AI SDK) |
46
46
  | **Developer Experience** | • Automatic Git initialization<br>• Package manager choice (npm, pnpm, bun)<br>• Automatic dependency installation |
47
47
 
48
- ## MCP (Model Context Protocol) Support
49
-
50
- The CLI now supports the Model Context Protocol, allowing AI assistants to scaffold projects programmatically. This enables seamless integration with AI coding assistants like Claude, Cursor, and others.
51
-
52
- ### Quick Start with MCP
53
-
54
- ```bash
55
- # Start the MCP server
56
- npx create-better-t-stack --mcp
57
- ```
58
-
59
- ### MCP Client Configuration
60
-
61
- Add to your MCP client configuration:
62
-
63
- ```json
64
- {
65
- "mcpServers": {
66
- "better-t-stack": {
67
- "command": "npx",
68
- "args": ["-y", "create-better-t-stack", "--mcp"]
69
- }
70
- }
71
- }
72
- ```
73
-
74
- ### Available MCP Tools
75
-
76
- - **`create_project`** - Create a new Better-T Stack project with specified configuration
77
- - **`list_configurations`** - List all available configuration options
78
- - **`get_project_info`** - Get information about an existing project
79
-
80
- For detailed MCP documentation, see [MCP_README.md](./MCP_README.md).
81
-
82
48
  ## Usage
83
49
 
84
50
  ```bash
package/dist/cli.js CHANGED
@@ -1,426 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { createBtsCli, init } from "./src-BN1_H4yj.js";
3
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
- import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
2
+ import { createBtsCli } from "./src-tnvyXvhu.js";
6
3
 
7
- //#region src/mcp-server.ts
8
- const server = new Server({
9
- name: "create-better-t-stack",
10
- version: "1.0.0"
11
- });
12
- const createProjectTool = {
13
- name: "create_project",
14
- description: "Create a new Better-T Stack project with the specified configuration",
15
- inputSchema: {
16
- type: "object",
17
- properties: {
18
- projectName: {
19
- type: "string",
20
- description: "Name of the project to create"
21
- },
22
- database: {
23
- type: "string",
24
- enum: [
25
- "none",
26
- "sqlite",
27
- "postgres",
28
- "mysql",
29
- "mongodb"
30
- ],
31
- description: "Database type to use"
32
- },
33
- orm: {
34
- type: "string",
35
- enum: [
36
- "drizzle",
37
- "prisma",
38
- "mongoose",
39
- "none"
40
- ],
41
- description: "ORM to use"
42
- },
43
- backend: {
44
- type: "string",
45
- enum: [
46
- "hono",
47
- "express",
48
- "fastify",
49
- "next",
50
- "elysia",
51
- "convex",
52
- "none"
53
- ],
54
- description: "Backend framework to use"
55
- },
56
- runtime: {
57
- type: "string",
58
- enum: [
59
- "bun",
60
- "node",
61
- "workers",
62
- "none"
63
- ],
64
- description: "Runtime environment"
65
- },
66
- frontend: {
67
- type: "array",
68
- items: {
69
- type: "string",
70
- enum: [
71
- "tanstack-router",
72
- "react-router",
73
- "tanstack-start",
74
- "next",
75
- "nuxt",
76
- "native-nativewind",
77
- "native-unistyles",
78
- "svelte",
79
- "solid",
80
- "none"
81
- ]
82
- },
83
- description: "Frontend frameworks to use"
84
- },
85
- addons: {
86
- type: "array",
87
- items: {
88
- type: "string",
89
- enum: [
90
- "pwa",
91
- "tauri",
92
- "starlight",
93
- "biome",
94
- "husky",
95
- "ruler",
96
- "turborepo",
97
- "fumadocs",
98
- "ultracite",
99
- "oxlint",
100
- "none"
101
- ]
102
- },
103
- description: "Addons to include"
104
- },
105
- examples: {
106
- type: "array",
107
- items: {
108
- type: "string",
109
- enum: [
110
- "todo",
111
- "ai",
112
- "none"
113
- ]
114
- },
115
- description: "Example templates to include"
116
- },
117
- auth: {
118
- type: "boolean",
119
- description: "Whether to include authentication"
120
- },
121
- git: {
122
- type: "boolean",
123
- description: "Whether to initialize git repository"
124
- },
125
- packageManager: {
126
- type: "string",
127
- enum: [
128
- "npm",
129
- "pnpm",
130
- "bun"
131
- ],
132
- description: "Package manager to use"
133
- },
134
- install: {
135
- type: "boolean",
136
- description: "Whether to install dependencies"
137
- },
138
- dbSetup: {
139
- type: "string",
140
- enum: [
141
- "turso",
142
- "neon",
143
- "prisma-postgres",
144
- "mongodb-atlas",
145
- "supabase",
146
- "d1",
147
- "docker",
148
- "none"
149
- ],
150
- description: "Database setup configuration"
151
- },
152
- api: {
153
- type: "string",
154
- enum: [
155
- "trpc",
156
- "orpc",
157
- "none"
158
- ],
159
- description: "API type to use"
160
- },
161
- webDeploy: {
162
- type: "string",
163
- enum: [
164
- "vercel",
165
- "netlify",
166
- "wrangler",
167
- "alchemy",
168
- "none"
169
- ],
170
- description: "Web deployment platform"
171
- },
172
- serverDeploy: {
173
- type: "string",
174
- enum: [
175
- "wrangler",
176
- "alchemy",
177
- "none"
178
- ],
179
- description: "Server deployment platform"
180
- },
181
- directoryConflict: {
182
- type: "string",
183
- enum: [
184
- "merge",
185
- "overwrite",
186
- "increment",
187
- "error"
188
- ],
189
- description: "How to handle directory conflicts"
190
- },
191
- yes: {
192
- type: "boolean",
193
- description: "Use default configuration without prompts"
194
- },
195
- yolo: {
196
- type: "boolean",
197
- description: "Bypass validations and compatibility checks"
198
- },
199
- verbose: {
200
- type: "boolean",
201
- description: "Show detailed result information"
202
- },
203
- disableAnalytics: {
204
- type: "boolean",
205
- description: "Disable analytics"
206
- }
207
- },
208
- required: ["projectName"]
209
- }
210
- };
211
- const listConfigurationsTool = {
212
- name: "list_configurations",
213
- description: "List available configurations for Better-T Stack projects",
214
- inputSchema: {
215
- type: "object",
216
- properties: {}
217
- }
218
- };
219
- const getProjectInfoTool = {
220
- name: "get_project_info",
221
- description: "Get information about a Better-T Stack project",
222
- inputSchema: {
223
- type: "object",
224
- properties: { projectPath: {
225
- type: "string",
226
- description: "Path to the project directory"
227
- } },
228
- required: ["projectPath"]
229
- }
230
- };
231
- server.setRequestHandler(ListToolsRequestSchema, async () => {
232
- return { tools: [
233
- createProjectTool,
234
- listConfigurationsTool,
235
- getProjectInfoTool
236
- ] };
237
- });
238
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
239
- const { name, arguments: args } = request.params;
240
- switch (name) {
241
- case "create_project": try {
242
- const projectConfig = {
243
- projectName: args?.projectName,
244
- database: args?.database,
245
- orm: args?.orm,
246
- backend: args?.backend,
247
- runtime: args?.runtime,
248
- frontend: args?.frontend,
249
- addons: args?.addons,
250
- examples: args?.examples,
251
- auth: args?.auth,
252
- git: args?.git,
253
- packageManager: args?.packageManager,
254
- install: args?.install,
255
- dbSetup: args?.dbSetup,
256
- api: args?.api,
257
- webDeploy: args?.webDeploy,
258
- serverDeploy: args?.serverDeploy,
259
- directoryConflict: args?.directoryConflict,
260
- yes: args?.yes,
261
- yolo: args?.yolo,
262
- verbose: args?.verbose,
263
- disableAnalytics: args?.disableAnalytics
264
- };
265
- const result = await init(args?.projectName, projectConfig);
266
- return { content: [{
267
- type: "text",
268
- text: JSON.stringify(result, null, 2)
269
- }] };
270
- } catch (error) {
271
- return {
272
- content: [{
273
- type: "text",
274
- text: `Error creating project: ${error instanceof Error ? error.message : String(error)}`
275
- }],
276
- isError: true
277
- };
278
- }
279
- case "list_configurations": {
280
- const configurations = {
281
- databases: [
282
- "none",
283
- "sqlite",
284
- "postgres",
285
- "mysql",
286
- "mongodb"
287
- ],
288
- orms: [
289
- "drizzle",
290
- "prisma",
291
- "mongoose",
292
- "none"
293
- ],
294
- backends: [
295
- "hono",
296
- "express",
297
- "fastify",
298
- "next",
299
- "elysia",
300
- "convex",
301
- "none"
302
- ],
303
- runtimes: [
304
- "bun",
305
- "node",
306
- "workers",
307
- "none"
308
- ],
309
- frontends: [
310
- "tanstack-router",
311
- "react-router",
312
- "tanstack-start",
313
- "next",
314
- "nuxt",
315
- "native-nativewind",
316
- "native-unistyles",
317
- "svelte",
318
- "solid",
319
- "none"
320
- ],
321
- addons: [
322
- "pwa",
323
- "tauri",
324
- "starlight",
325
- "biome",
326
- "husky",
327
- "ruler",
328
- "turborepo",
329
- "fumadocs",
330
- "ultracite",
331
- "oxlint",
332
- "none"
333
- ],
334
- examples: [
335
- "todo",
336
- "ai",
337
- "none"
338
- ],
339
- packageManagers: [
340
- "npm",
341
- "pnpm",
342
- "bun"
343
- ],
344
- dbSetups: [
345
- "turso",
346
- "neon",
347
- "prisma-postgres",
348
- "mongodb-atlas",
349
- "supabase",
350
- "d1",
351
- "docker",
352
- "none"
353
- ],
354
- apis: [
355
- "trpc",
356
- "orpc",
357
- "none"
358
- ],
359
- webDeploys: [
360
- "vercel",
361
- "netlify",
362
- "wrangler",
363
- "alchemy",
364
- "none"
365
- ],
366
- serverDeploys: [
367
- "wrangler",
368
- "alchemy",
369
- "none"
370
- ],
371
- directoryConflicts: [
372
- "merge",
373
- "overwrite",
374
- "increment",
375
- "error"
376
- ]
377
- };
378
- return { content: [{
379
- type: "text",
380
- text: JSON.stringify(configurations, null, 2)
381
- }] };
382
- }
383
- case "get_project_info": try {
384
- return { content: [{
385
- type: "text",
386
- text: "Project info functionality not yet implemented"
387
- }] };
388
- } catch (error) {
389
- return {
390
- content: [{
391
- type: "text",
392
- text: `Error getting project info: ${error instanceof Error ? error.message : String(error)}`
393
- }],
394
- isError: true
395
- };
396
- }
397
- default: throw new Error(`Unknown tool: ${name}`);
398
- }
399
- });
400
- async function startMCPServer() {
401
- const transport = new StdioServerTransport();
402
- await server.connect(transport);
403
- console.error("Better-T Stack MCP server started");
404
- }
405
- async function main$1() {
406
- await startMCPServer();
407
- }
408
- if (import.meta.url === `file://${process.argv[1]}`) main$1().catch((error) => {
409
- console.error("MCP server error:", error);
410
- process.exit(1);
411
- });
412
-
413
- //#endregion
414
4
  //#region src/cli.ts
415
- async function main() {
416
- const args = process.argv.slice(2);
417
- if (args.includes("--mcp")) await startMCPServer();
418
- else createBtsCli().run();
419
- }
420
- main().catch((error) => {
421
- console.error("CLI error:", error);
422
- process.exit(1);
423
- });
5
+ createBtsCli().run();
424
6
 
425
7
  //#endregion
426
8
  export { };
package/dist/index.d.ts CHANGED
@@ -134,7 +134,6 @@ type CreateInput = {
134
134
  directoryConflict?: DirectoryConflict;
135
135
  renderTitle?: boolean;
136
136
  disableAnalytics?: boolean;
137
- mcp?: boolean;
138
137
  };
139
138
  type AddInput = {
140
139
  addons?: Addons[];
@@ -222,7 +221,6 @@ declare const router: trpcServer.TRPCBuiltRouter<{
222
221
  directoryConflict?: "error" | "merge" | "overwrite" | "increment" | undefined;
223
222
  renderTitle?: boolean | undefined;
224
223
  disableAnalytics?: boolean | undefined;
225
- mcp?: boolean | undefined;
226
224
  }];
227
225
  output: InitResult | undefined;
228
226
  meta: object;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { builder, createBtsCli, docs, init, router, sponsors } from "./src-BN1_H4yj.js";
2
+ import { builder, createBtsCli, docs, init, router, sponsors } from "./src-tnvyXvhu.js";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { cancel, confirm, group, groupMultiselect, intro, isCancel, log, multiselect, outro, select, spinner, text } from "@clack/prompts";
2
+ import { autocompleteMultiselect, cancel, confirm, group, groupMultiselect, intro, isCancel, log, multiselect, outro, select, spinner, text } from "@clack/prompts";
3
3
  import pc from "picocolors";
4
4
  import { createCli, trpcServer } from "trpc-cli";
5
5
  import z from "zod";
@@ -1309,7 +1309,7 @@ async function getProjectName(initialName) {
1309
1309
  initialValue: initialName,
1310
1310
  defaultValue: defaultName,
1311
1311
  validate: (value) => {
1312
- const nameToUse = value.trim() || defaultName;
1312
+ const nameToUse = String(value ?? "").trim() || defaultName;
1313
1313
  const finalDirName = path.basename(nameToUse);
1314
1314
  const validationError = validateDirectoryName(finalDirName);
1315
1315
  if (validationError) return validationError;
@@ -1345,7 +1345,7 @@ const getLatestCLIVersion = () => {
1345
1345
  */
1346
1346
  function isTelemetryEnabled() {
1347
1347
  const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
1348
- const BTS_TELEMETRY = "0";
1348
+ const BTS_TELEMETRY = "1";
1349
1349
  if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
1350
1350
  if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
1351
1351
  return true;
@@ -1353,8 +1353,8 @@ function isTelemetryEnabled() {
1353
1353
 
1354
1354
  //#endregion
1355
1355
  //#region src/utils/analytics.ts
1356
- const POSTHOG_API_KEY = "random";
1357
- const POSTHOG_HOST = "random";
1356
+ const POSTHOG_API_KEY = "phc_8ZUxEwwfKMajJLvxz1daGd931dYbQrwKNficBmsdIrs";
1357
+ const POSTHOG_HOST = "https://us.i.posthog.com";
1358
1358
  function generateSessionId() {
1359
1359
  const rand = Math.random().toString(36).slice(2);
1360
1360
  const now = Date.now().toString(36);
@@ -2429,7 +2429,7 @@ async function setupVibeRules(config) {
2429
2429
  kilocode: { label: "Kilo Code" },
2430
2430
  opencode: { label: "OpenCode" }
2431
2431
  };
2432
- const selectedEditors = await multiselect({
2432
+ const selectedEditors = await autocompleteMultiselect({
2433
2433
  message: "Select AI assistants for Ruler",
2434
2434
  options: Object.entries(EDITORS$1).map(([key, v]) => ({
2435
2435
  value: key,
@@ -2572,66 +2572,55 @@ async function setupTauri(config) {
2572
2572
  //#endregion
2573
2573
  //#region src/helpers/addons/ultracite-setup.ts
2574
2574
  const EDITORS = {
2575
- vscode: {
2576
- label: "VSCode / Cursor / Windsurf",
2577
- hint: "Visual Studio Code editor configuration"
2578
- },
2579
- zed: {
2580
- label: "Zed",
2581
- hint: "Zed editor configuration"
2582
- }
2575
+ vscode: { label: "VSCode / Cursor / Windsurf" },
2576
+ zed: { label: "Zed" }
2583
2577
  };
2584
2578
  const RULES = {
2585
- "vscode-copilot": {
2586
- label: "VS Code Copilot",
2587
- hint: "GitHub Copilot integration for VS Code"
2588
- },
2589
- cursor: {
2590
- label: "Cursor",
2591
- hint: "Cursor AI editor configuration"
2592
- },
2593
- windsurf: {
2594
- label: "Windsurf",
2595
- hint: "Windsurf editor configuration"
2596
- },
2597
- zed: {
2598
- label: "Zed",
2599
- hint: "Zed editor rules"
2600
- },
2601
- claude: {
2602
- label: "Claude",
2603
- hint: "Claude AI integration"
2604
- },
2605
- codex: {
2606
- label: "Codex",
2607
- hint: "Codex AI integration"
2608
- }
2579
+ "vscode-copilot": { label: "VS Code Copilot" },
2580
+ cursor: { label: "Cursor" },
2581
+ windsurf: { label: "Windsurf" },
2582
+ zed: { label: "Zed" },
2583
+ claude: { label: "Claude" },
2584
+ codex: { label: "Codex" },
2585
+ kiro: { label: "Kiro" },
2586
+ cline: { label: "Cline" },
2587
+ amp: { label: "Amp" },
2588
+ aider: { label: "Aider" },
2589
+ "firebase-studio": { label: "Firebase Studio" },
2590
+ "open-hands": { label: "Open Hands" },
2591
+ "gemini-cli": { label: "Gemini CLI" },
2592
+ junie: { label: "Junie" },
2593
+ augmentcode: { label: "AugmentCode" },
2594
+ "kilo-code": { label: "Kilo Code" },
2595
+ goose: { label: "Goose" }
2609
2596
  };
2610
2597
  async function setupUltracite(config, hasHusky) {
2611
2598
  const { packageManager, projectDir } = config;
2612
2599
  try {
2613
2600
  log.info("Setting up Ultracite...");
2614
2601
  await setupBiome(projectDir);
2615
- const editors = await multiselect({
2616
- message: "Choose editors",
2617
- options: Object.entries(EDITORS).map(([key, editor]) => ({
2618
- value: key,
2619
- label: editor.label,
2620
- hint: editor.hint
2621
- })),
2622
- required: true
2623
- });
2624
- if (isCancel(editors)) return exitCancelled("Operation cancelled");
2625
- const rules = await multiselect({
2626
- message: "Choose rules",
2627
- options: Object.entries(RULES).map(([key, rule]) => ({
2628
- value: key,
2629
- label: rule.label,
2630
- hint: rule.hint
2631
- })),
2632
- required: true
2633
- });
2634
- if (isCancel(rules)) return exitCancelled("Operation cancelled");
2602
+ const result = await group({
2603
+ editors: () => multiselect({
2604
+ message: "Choose editors",
2605
+ options: Object.entries(EDITORS).map(([key, editor]) => ({
2606
+ value: key,
2607
+ label: editor.label
2608
+ })),
2609
+ required: true
2610
+ }),
2611
+ rules: () => autocompleteMultiselect({
2612
+ message: "Choose rules",
2613
+ options: Object.entries(RULES).map(([key, rule]) => ({
2614
+ value: key,
2615
+ label: rule.label
2616
+ })),
2617
+ required: true
2618
+ })
2619
+ }, { onCancel: () => {
2620
+ exitCancelled("Operation cancelled");
2621
+ } });
2622
+ const editors = result.editors;
2623
+ const rules = result.rules;
2635
2624
  const ultraciteArgs = [
2636
2625
  "init",
2637
2626
  "--pm",
@@ -6320,8 +6309,7 @@ const router = t.router({
6320
6309
  serverDeploy: ServerDeploySchema.optional(),
6321
6310
  directoryConflict: DirectoryConflictSchema.optional(),
6322
6311
  renderTitle: z.boolean().optional(),
6323
- disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics"),
6324
- mcp: z.boolean().optional().default(false).describe("Start as MCP server")
6312
+ disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics")
6325
6313
  })])).mutation(async ({ input }) => {
6326
6314
  const [projectName, options] = input;
6327
6315
  const combinedInput = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.35.5-canary.869063df",
3
+ "version": "2.36.0",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -66,8 +66,7 @@
66
66
  "dependencies": {
67
67
  "@biomejs/js-api": "^3.0.0",
68
68
  "@biomejs/wasm-nodejs": "^2.2.0",
69
- "@clack/prompts": "^0.11.0",
70
- "@modelcontextprotocol/sdk": "^0.4.0",
69
+ "@clack/prompts": "^1.0.0-alpha.4",
71
70
  "consola": "^3.4.2",
72
71
  "execa": "^9.6.0",
73
72
  "fs-extra": "^11.3.1",