@girardmedia/bootspring 1.1.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/LICENSE +21 -0
- package/README.md +255 -0
- package/agents/README.md +93 -0
- package/agents/api-expert/context.md +416 -0
- package/agents/architecture-expert/context.md +454 -0
- package/agents/backend-expert/context.md +483 -0
- package/agents/code-review-expert/context.md +365 -0
- package/agents/database-expert/context.md +250 -0
- package/agents/devops-expert/context.md +446 -0
- package/agents/frontend-expert/context.md +364 -0
- package/agents/index.js +140 -0
- package/agents/performance-expert/context.md +377 -0
- package/agents/security-expert/context.md +343 -0
- package/agents/testing-expert/context.md +414 -0
- package/agents/ui-ux-expert/context.md +448 -0
- package/agents/vercel-expert/context.md +426 -0
- package/bin/bootspring.js +310 -0
- package/cli/agent.js +337 -0
- package/cli/context.js +194 -0
- package/cli/dashboard.js +150 -0
- package/cli/generate.js +294 -0
- package/cli/init.js +410 -0
- package/cli/loop.js +421 -0
- package/cli/mcp.js +241 -0
- package/cli/memory.js +303 -0
- package/cli/orchestrator.js +400 -0
- package/cli/plugin.js +451 -0
- package/cli/quality.js +332 -0
- package/cli/skill.js +369 -0
- package/cli/task.js +628 -0
- package/cli/telemetry.js +114 -0
- package/cli/todo.js +614 -0
- package/cli/update.js +312 -0
- package/core/config.js +245 -0
- package/core/context.js +329 -0
- package/core/entitlements.js +209 -0
- package/core/index.js +43 -0
- package/core/policies.js +68 -0
- package/core/telemetry.js +247 -0
- package/core/utils.js +380 -0
- package/dashboard/server.js +818 -0
- package/docs/integrations/claude-code.md +42 -0
- package/docs/integrations/codex.md +42 -0
- package/docs/mcp-api-platform.md +102 -0
- package/generators/generate.js +598 -0
- package/generators/index.js +18 -0
- package/hooks/context-detector.js +177 -0
- package/hooks/index.js +35 -0
- package/hooks/prompt-enhancer.js +289 -0
- package/intelligence/git-memory.js +551 -0
- package/intelligence/index.js +59 -0
- package/intelligence/orchestrator.js +964 -0
- package/intelligence/prd.js +447 -0
- package/intelligence/recommendation-weights.json +18 -0
- package/intelligence/recommendations.js +234 -0
- package/mcp/capabilities.js +71 -0
- package/mcp/contracts/mcp-contract.v1.json +497 -0
- package/mcp/registry.js +213 -0
- package/mcp/response-formatter.js +462 -0
- package/mcp/server.js +99 -0
- package/mcp/tools/agent-tool.js +137 -0
- package/mcp/tools/capabilities-tool.js +54 -0
- package/mcp/tools/context-tool.js +49 -0
- package/mcp/tools/dashboard-tool.js +58 -0
- package/mcp/tools/generate-tool.js +46 -0
- package/mcp/tools/loop-tool.js +134 -0
- package/mcp/tools/memory-tool.js +180 -0
- package/mcp/tools/orchestrator-tool.js +232 -0
- package/mcp/tools/plugin-tool.js +76 -0
- package/mcp/tools/quality-tool.js +47 -0
- package/mcp/tools/skill-tool.js +233 -0
- package/mcp/tools/telemetry-tool.js +95 -0
- package/mcp/tools/todo-tool.js +133 -0
- package/package.json +98 -0
- package/plugins/index.js +141 -0
- package/quality/index.js +380 -0
- package/quality/lint-budgets.json +19 -0
- package/skills/index.js +787 -0
- package/skills/patterns/README.md +163 -0
- package/skills/patterns/api/route-handler.md +217 -0
- package/skills/patterns/api/server-action.md +249 -0
- package/skills/patterns/auth/clerk.md +132 -0
- package/skills/patterns/database/prisma.md +180 -0
- package/skills/patterns/payments/stripe.md +272 -0
- package/skills/patterns/security/validation.md +268 -0
- package/skills/patterns/testing/vitest.md +307 -0
- package/templates/bootspring.config.js +83 -0
- package/templates/mcp.json +9 -0
package/cli/init.js
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Init Command
|
|
3
|
+
* Initialize Bootspring in a new or existing project
|
|
4
|
+
*
|
|
5
|
+
* @package bootspring
|
|
6
|
+
* @command init
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const readline = require('readline');
|
|
12
|
+
const config = require('../core/config');
|
|
13
|
+
const utils = require('../core/utils');
|
|
14
|
+
|
|
15
|
+
// Available options
|
|
16
|
+
const FRAMEWORKS = ['nextjs', 'remix', 'nuxt', 'sveltekit', 'express', 'fastify', 'other'];
|
|
17
|
+
const LANGUAGES = ['typescript', 'javascript'];
|
|
18
|
+
const DATABASES = ['postgresql', 'mysql', 'mongodb', 'sqlite', 'none'];
|
|
19
|
+
const HOSTINGS = ['vercel', 'netlify', 'railway', 'fly', 'aws', 'self-hosted'];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create readline interface for interactive prompts
|
|
23
|
+
*/
|
|
24
|
+
function createPrompt() {
|
|
25
|
+
return readline.createInterface({
|
|
26
|
+
input: process.stdin,
|
|
27
|
+
output: process.stdout
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Ask a question and return the answer
|
|
33
|
+
*/
|
|
34
|
+
function ask(rl, question, defaultValue = '') {
|
|
35
|
+
const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
rl.question(prompt, (answer) => {
|
|
38
|
+
resolve(answer.trim() || defaultValue);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Ask a multiple choice question
|
|
45
|
+
*/
|
|
46
|
+
function askChoice(rl, question, options, defaultIndex = 0) {
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
console.log(`\n${question}`);
|
|
49
|
+
options.forEach((opt, i) => {
|
|
50
|
+
const marker = i === defaultIndex ? `${utils.COLORS.cyan}→${utils.COLORS.reset}` : ' ';
|
|
51
|
+
console.log(` ${marker} ${i + 1}. ${opt}`);
|
|
52
|
+
});
|
|
53
|
+
rl.question(`\nSelect [1-${options.length}] (default: ${defaultIndex + 1}): `, (answer) => {
|
|
54
|
+
const index = parseInt(answer, 10) - 1;
|
|
55
|
+
if (index >= 0 && index < options.length) {
|
|
56
|
+
resolve(options[index]);
|
|
57
|
+
} else {
|
|
58
|
+
resolve(options[defaultIndex]);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Ask yes/no question
|
|
66
|
+
*/
|
|
67
|
+
function askYesNo(rl, question, defaultYes = true) {
|
|
68
|
+
const hint = defaultYes ? '[Y/n]' : '[y/N]';
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
rl.question(`${question} ${hint}: `, (answer) => {
|
|
71
|
+
const a = answer.trim().toLowerCase();
|
|
72
|
+
if (a === '') {
|
|
73
|
+
resolve(defaultYes);
|
|
74
|
+
} else {
|
|
75
|
+
resolve(a === 'y' || a === 'yes');
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Detect project info from existing files
|
|
83
|
+
*/
|
|
84
|
+
function detectProject(projectRoot) {
|
|
85
|
+
const detected = {
|
|
86
|
+
name: path.basename(projectRoot),
|
|
87
|
+
framework: 'nextjs',
|
|
88
|
+
language: 'typescript',
|
|
89
|
+
database: 'postgresql',
|
|
90
|
+
hosting: 'vercel'
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Check package.json
|
|
94
|
+
const pkg = utils.getPackageJson(projectRoot);
|
|
95
|
+
if (pkg) {
|
|
96
|
+
detected.name = pkg.name || detected.name;
|
|
97
|
+
|
|
98
|
+
// Detect framework
|
|
99
|
+
if (pkg.dependencies?.next || pkg.devDependencies?.next) {
|
|
100
|
+
detected.framework = 'nextjs';
|
|
101
|
+
} else if (pkg.dependencies?.remix || pkg.devDependencies?.remix) {
|
|
102
|
+
detected.framework = 'remix';
|
|
103
|
+
} else if (pkg.dependencies?.nuxt || pkg.devDependencies?.nuxt) {
|
|
104
|
+
detected.framework = 'nuxt';
|
|
105
|
+
} else if (pkg.dependencies?.['@sveltejs/kit']) {
|
|
106
|
+
detected.framework = 'sveltekit';
|
|
107
|
+
} else if (pkg.dependencies?.express) {
|
|
108
|
+
detected.framework = 'express';
|
|
109
|
+
} else if (pkg.dependencies?.fastify) {
|
|
110
|
+
detected.framework = 'fastify';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Detect database
|
|
114
|
+
if (pkg.dependencies?.['@prisma/client']) {
|
|
115
|
+
detected.database = 'postgresql';
|
|
116
|
+
} else if (pkg.dependencies?.mongoose) {
|
|
117
|
+
detected.database = 'mongodb';
|
|
118
|
+
} else if (pkg.dependencies?.mysql2) {
|
|
119
|
+
detected.database = 'mysql';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Detect TypeScript
|
|
124
|
+
if (utils.fileExists(path.join(projectRoot, 'tsconfig.json'))) {
|
|
125
|
+
detected.language = 'typescript';
|
|
126
|
+
} else {
|
|
127
|
+
detected.language = 'javascript';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Detect Vercel
|
|
131
|
+
if (utils.fileExists(path.join(projectRoot, 'vercel.json'))) {
|
|
132
|
+
detected.hosting = 'vercel';
|
|
133
|
+
} else if (utils.fileExists(path.join(projectRoot, 'netlify.toml'))) {
|
|
134
|
+
detected.hosting = 'netlify';
|
|
135
|
+
} else if (utils.fileExists(path.join(projectRoot, 'fly.toml'))) {
|
|
136
|
+
detected.hosting = 'fly';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return detected;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generate CLAUDE.md content
|
|
144
|
+
*/
|
|
145
|
+
function generateClaudeMd(projectConfig) {
|
|
146
|
+
const date = utils.formatDate();
|
|
147
|
+
|
|
148
|
+
return `# ${projectConfig.project.name} - AI Context
|
|
149
|
+
|
|
150
|
+
**Generated by**: Bootspring v1.0.0
|
|
151
|
+
**Last Updated**: ${date}
|
|
152
|
+
**Documentation**: https://bootspring.com/docs
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Project Overview
|
|
157
|
+
|
|
158
|
+
${projectConfig.project.description || 'A project scaffolded with Bootspring.'}
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Tech Stack
|
|
163
|
+
|
|
164
|
+
- **Framework**: ${projectConfig.stack.framework}
|
|
165
|
+
- **Language**: ${projectConfig.stack.language}
|
|
166
|
+
- **Database**: ${projectConfig.stack.database}
|
|
167
|
+
- **Hosting**: ${projectConfig.stack.hosting}
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Bootspring Commands
|
|
172
|
+
|
|
173
|
+
Use these commands with your AI assistant:
|
|
174
|
+
|
|
175
|
+
| Command | Description |
|
|
176
|
+
|---------|-------------|
|
|
177
|
+
| \`bootspring todo add "task"\` | Add a new todo item |
|
|
178
|
+
| \`bootspring todo list\` | List all todos |
|
|
179
|
+
| \`bootspring todo done <id>\` | Mark todo as complete |
|
|
180
|
+
| \`bootspring agent list\` | List available agents |
|
|
181
|
+
| \`bootspring agent invoke <name>\` | Get specialized help |
|
|
182
|
+
| \`bootspring skill search <query>\` | Find code patterns |
|
|
183
|
+
| \`bootspring dashboard\` | Start real-time dashboard |
|
|
184
|
+
| \`bootspring quality pre-commit\` | Run quality checks |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Enabled Plugins
|
|
189
|
+
|
|
190
|
+
${Object.entries(projectConfig.plugins)
|
|
191
|
+
.filter(([_, p]) => p.enabled !== false)
|
|
192
|
+
.map(([name, plugin]) => `### ${name.charAt(0).toUpperCase() + name.slice(1)}
|
|
193
|
+
- Provider: ${plugin.provider || 'default'}
|
|
194
|
+
- Features: ${(plugin.features || []).join(', ') || 'default'}`)
|
|
195
|
+
.join('\n\n')}
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Development Workflow
|
|
200
|
+
|
|
201
|
+
1. **Start dashboard**: \`bootspring dashboard\` for real-time visibility
|
|
202
|
+
2. **Track work**: Use \`bootspring todo\` to manage tasks
|
|
203
|
+
3. **Get help**: Invoke agents for specialized expertise
|
|
204
|
+
4. **Quality**: Run \`bootspring quality pre-commit\` before committing
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Custom Instructions
|
|
209
|
+
|
|
210
|
+
- Use Server Components by default (Next.js)
|
|
211
|
+
- Prefer Server Actions over API routes for mutations
|
|
212
|
+
- Use Zod for all input validation
|
|
213
|
+
- Follow existing file naming conventions
|
|
214
|
+
- Keep components small and focused
|
|
215
|
+
- Write tests for new features
|
|
216
|
+
- Never expose API keys to client-side code
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
*Generated by [Bootspring](https://bootspring.com) - Development scaffolding with intelligence*
|
|
221
|
+
`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Generate todo.md content
|
|
226
|
+
*/
|
|
227
|
+
function generateTodoMd(projectName) {
|
|
228
|
+
const date = utils.formatDate();
|
|
229
|
+
|
|
230
|
+
return `# ${projectName} - Todo List
|
|
231
|
+
|
|
232
|
+
> Last updated: ${date}
|
|
233
|
+
|
|
234
|
+
## In Progress
|
|
235
|
+
|
|
236
|
+
- [ ] Complete project setup
|
|
237
|
+
|
|
238
|
+
## Pending
|
|
239
|
+
|
|
240
|
+
- [ ] Configure environment variables
|
|
241
|
+
- [ ] Set up database schema
|
|
242
|
+
- [ ] Implement core features
|
|
243
|
+
|
|
244
|
+
## Completed
|
|
245
|
+
|
|
246
|
+
`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Run init command
|
|
251
|
+
*/
|
|
252
|
+
async function run(args) {
|
|
253
|
+
const parsedArgs = utils.parseArgs(args);
|
|
254
|
+
const force = parsedArgs.force || parsedArgs.f;
|
|
255
|
+
const quick = parsedArgs.quick || parsedArgs.q;
|
|
256
|
+
const projectRoot = config.findProjectRoot();
|
|
257
|
+
|
|
258
|
+
console.log(`
|
|
259
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Init${utils.COLORS.reset}
|
|
260
|
+
${utils.COLORS.dim}Development scaffolding with intelligence${utils.COLORS.reset}
|
|
261
|
+
`);
|
|
262
|
+
|
|
263
|
+
// Check if already initialized
|
|
264
|
+
const existingConfig = config.findConfigFile(projectRoot);
|
|
265
|
+
if (existingConfig && !force) {
|
|
266
|
+
utils.print.warning(`Project already initialized at ${projectRoot}`);
|
|
267
|
+
utils.print.dim(`Use --force to reinitialize`);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Detect existing project settings
|
|
272
|
+
const detected = detectProject(projectRoot);
|
|
273
|
+
utils.print.info(`Detected project: ${detected.name}`);
|
|
274
|
+
utils.print.dim(`Root: ${projectRoot}`);
|
|
275
|
+
|
|
276
|
+
let projectConfig;
|
|
277
|
+
|
|
278
|
+
if (quick) {
|
|
279
|
+
// Quick mode - use detected values
|
|
280
|
+
utils.print.info('Using detected settings (quick mode)');
|
|
281
|
+
projectConfig = {
|
|
282
|
+
project: {
|
|
283
|
+
name: detected.name,
|
|
284
|
+
description: '',
|
|
285
|
+
version: '1.0.0'
|
|
286
|
+
},
|
|
287
|
+
stack: {
|
|
288
|
+
framework: detected.framework,
|
|
289
|
+
language: detected.language,
|
|
290
|
+
database: detected.database,
|
|
291
|
+
hosting: detected.hosting
|
|
292
|
+
},
|
|
293
|
+
plugins: {
|
|
294
|
+
auth: { enabled: false, provider: 'clerk' },
|
|
295
|
+
payments: { enabled: false, provider: 'stripe' },
|
|
296
|
+
database: { enabled: detected.database !== 'none', provider: 'prisma' },
|
|
297
|
+
testing: { enabled: true, provider: 'vitest' },
|
|
298
|
+
security: { enabled: true },
|
|
299
|
+
ai: { enabled: false, provider: 'anthropic' }
|
|
300
|
+
},
|
|
301
|
+
dashboard: { port: 3456, autoOpen: false },
|
|
302
|
+
quality: { preCommit: true, prePush: false, strictMode: false },
|
|
303
|
+
paths: { context: 'CLAUDE.md', config: 'bootspring.config.js', todo: 'todo.md' }
|
|
304
|
+
};
|
|
305
|
+
} else {
|
|
306
|
+
// Interactive mode
|
|
307
|
+
const rl = createPrompt();
|
|
308
|
+
|
|
309
|
+
console.log(`\n${utils.COLORS.bold}Project Configuration${utils.COLORS.reset}`);
|
|
310
|
+
|
|
311
|
+
const name = await ask(rl, 'Project name', detected.name);
|
|
312
|
+
const description = await ask(rl, 'Description', '');
|
|
313
|
+
const framework = await askChoice(rl, 'Framework:', FRAMEWORKS, FRAMEWORKS.indexOf(detected.framework));
|
|
314
|
+
const language = await askChoice(rl, 'Language:', LANGUAGES, LANGUAGES.indexOf(detected.language));
|
|
315
|
+
const database = await askChoice(rl, 'Database:', DATABASES, DATABASES.indexOf(detected.database));
|
|
316
|
+
const hosting = await askChoice(rl, 'Hosting:', HOSTINGS, HOSTINGS.indexOf(detected.hosting));
|
|
317
|
+
|
|
318
|
+
console.log(`\n${utils.COLORS.bold}Plugins${utils.COLORS.reset}`);
|
|
319
|
+
|
|
320
|
+
const enableAuth = await askYesNo(rl, 'Enable auth plugin?', false);
|
|
321
|
+
const enablePayments = await askYesNo(rl, 'Enable payments plugin?', false);
|
|
322
|
+
const enableTesting = await askYesNo(rl, 'Enable testing plugin?', true);
|
|
323
|
+
const enableAI = await askYesNo(rl, 'Enable AI plugin?', false);
|
|
324
|
+
|
|
325
|
+
rl.close();
|
|
326
|
+
|
|
327
|
+
projectConfig = {
|
|
328
|
+
project: { name, description, version: '1.0.0' },
|
|
329
|
+
stack: { framework, language, database, hosting },
|
|
330
|
+
plugins: {
|
|
331
|
+
auth: { enabled: enableAuth, provider: 'clerk' },
|
|
332
|
+
payments: { enabled: enablePayments, provider: 'stripe' },
|
|
333
|
+
database: { enabled: database !== 'none', provider: 'prisma' },
|
|
334
|
+
testing: { enabled: enableTesting, provider: 'vitest' },
|
|
335
|
+
security: { enabled: true },
|
|
336
|
+
ai: { enabled: enableAI, provider: 'anthropic' }
|
|
337
|
+
},
|
|
338
|
+
dashboard: { port: 3456, autoOpen: false },
|
|
339
|
+
quality: { preCommit: true, prePush: false, strictMode: false },
|
|
340
|
+
paths: { context: 'CLAUDE.md', config: 'bootspring.config.js', todo: 'todo.md' }
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Create files
|
|
345
|
+
console.log(`\n${utils.COLORS.bold}Creating files...${utils.COLORS.reset}\n`);
|
|
346
|
+
|
|
347
|
+
// 1. bootspring.config.js
|
|
348
|
+
const configPath = path.join(projectRoot, 'bootspring.config.js');
|
|
349
|
+
const configSpinner = utils.createSpinner('Creating bootspring.config.js').start();
|
|
350
|
+
if (config.save(projectConfig, configPath)) {
|
|
351
|
+
configSpinner.succeed('Created bootspring.config.js');
|
|
352
|
+
} else {
|
|
353
|
+
configSpinner.fail('Failed to create bootspring.config.js');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 2. CLAUDE.md
|
|
357
|
+
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
358
|
+
const claudeSpinner = utils.createSpinner('Creating CLAUDE.md').start();
|
|
359
|
+
if (utils.writeFile(claudePath, generateClaudeMd(projectConfig))) {
|
|
360
|
+
claudeSpinner.succeed('Created CLAUDE.md');
|
|
361
|
+
} else {
|
|
362
|
+
claudeSpinner.fail('Failed to create CLAUDE.md');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// 3. todo.md (if not exists)
|
|
366
|
+
const todoPath = path.join(projectRoot, 'todo.md');
|
|
367
|
+
if (!utils.fileExists(todoPath)) {
|
|
368
|
+
const todoSpinner = utils.createSpinner('Creating todo.md').start();
|
|
369
|
+
if (utils.writeFile(todoPath, generateTodoMd(projectConfig.project.name))) {
|
|
370
|
+
todoSpinner.succeed('Created todo.md');
|
|
371
|
+
} else {
|
|
372
|
+
todoSpinner.fail('Failed to create todo.md');
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// 4. .mcp.json for Claude Code
|
|
377
|
+
const mcpPath = path.join(projectRoot, '.mcp.json');
|
|
378
|
+
if (!utils.fileExists(mcpPath)) {
|
|
379
|
+
const mcpSpinner = utils.createSpinner('Creating .mcp.json').start();
|
|
380
|
+
const mcpConfig = {
|
|
381
|
+
mcpServers: {
|
|
382
|
+
bootspring: {
|
|
383
|
+
command: 'npx',
|
|
384
|
+
args: ['bootspring', 'mcp'],
|
|
385
|
+
env: {}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
if (utils.writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2))) {
|
|
390
|
+
mcpSpinner.succeed('Created .mcp.json (MCP server config)');
|
|
391
|
+
} else {
|
|
392
|
+
mcpSpinner.fail('Failed to create .mcp.json');
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Success message
|
|
397
|
+
console.log(`
|
|
398
|
+
${utils.COLORS.green}${utils.COLORS.bold}✓ Bootspring initialized successfully!${utils.COLORS.reset}
|
|
399
|
+
|
|
400
|
+
${utils.COLORS.bold}Next steps:${utils.COLORS.reset}
|
|
401
|
+
|
|
402
|
+
1. Review ${utils.COLORS.cyan}bootspring.config.js${utils.COLORS.reset} and customize as needed
|
|
403
|
+
2. Start the dashboard: ${utils.COLORS.cyan}bootspring dashboard${utils.COLORS.reset}
|
|
404
|
+
3. Add your first todo: ${utils.COLORS.cyan}bootspring todo add "Your first task"${utils.COLORS.reset}
|
|
405
|
+
|
|
406
|
+
${utils.COLORS.dim}Documentation: https://bootspring.com/docs${utils.COLORS.reset}
|
|
407
|
+
`);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
module.exports = { run };
|