@codebakers/cli 1.2.0 → 1.3.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/dist/commands/install-hook.js +42 -68
- package/dist/commands/scaffold.d.ts +4 -0
- package/dist/commands/scaffold.js +205 -0
- package/dist/commands/setup.js +24 -12
- package/dist/index.js +6 -0
- package/dist/mcp/server.js +211 -0
- package/dist/templates/nextjs-supabase.d.ts +81 -0
- package/dist/templates/nextjs-supabase.js +356 -0
- package/package.json +1 -1
- package/src/commands/install-hook.ts +44 -68
- package/src/commands/scaffold.ts +196 -0
- package/src/commands/setup.ts +22 -14
- package/src/index.ts +7 -0
- package/src/mcp/server.ts +244 -0
- package/src/templates/nextjs-supabase.ts +371 -0
|
@@ -4,71 +4,40 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from
|
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
6
|
|
|
7
|
-
// Enhanced hook with
|
|
7
|
+
// Enhanced hook with visible feedback and concise instructions
|
|
8
8
|
const HOOK_TEMPLATE = {
|
|
9
9
|
hooks: {
|
|
10
10
|
UserPromptSubmit: [
|
|
11
11
|
{
|
|
12
12
|
type: "command",
|
|
13
|
-
command: `echo '
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- CLAUDE.md → Router & module instructions
|
|
22
|
-
- PRD.md → What we are building (requirements!)
|
|
23
|
-
- PROJECT-CONTEXT.md → Codebase knowledge
|
|
24
|
-
- PROJECT-STATE.md → What is in progress
|
|
25
|
-
- DECISIONS.md → Past architectural choices
|
|
26
|
-
|
|
27
|
-
▸ PHASE 2: PRE-FLIGHT CHECK (before writing code)
|
|
28
|
-
□ What existing code does this touch?
|
|
29
|
-
□ Is similar code in the codebase? (copy that pattern!)
|
|
30
|
-
□ Whats the data model?
|
|
31
|
-
□ What are the error cases?
|
|
32
|
-
□ Is someone else working on this? (check In Progress)
|
|
33
|
-
|
|
34
|
-
If PROJECT-CONTEXT.md is empty/stale, SCAN PROJECT FIRST:
|
|
35
|
-
- Read package.json
|
|
36
|
-
- Check file structure
|
|
37
|
-
- Find existing patterns
|
|
38
|
-
- Update PROJECT-CONTEXT.md
|
|
39
|
-
|
|
40
|
-
▸ PHASE 3: ACKNOWLEDGE & EXECUTE
|
|
41
|
-
Output: 📋 CodeBakers | [Type] | Modules: [list]
|
|
42
|
-
Then: Follow patterns from .claude/ folder EXACTLY
|
|
43
|
-
|
|
44
|
-
▸ PHASE 4: SELF-REVIEW (before saying done)
|
|
45
|
-
□ TypeScript compiles? (npx tsc --noEmit)
|
|
46
|
-
□ Imports resolve?
|
|
47
|
-
□ Error handling exists?
|
|
48
|
-
□ Matches existing patterns?
|
|
49
|
-
□ Tests written?
|
|
50
|
-
|
|
51
|
-
If ANY fails → FIX before responding
|
|
52
|
-
|
|
53
|
-
▸ PHASE 5: UPDATE STATE
|
|
54
|
-
- Update PROJECT-STATE.md (move to Completed)
|
|
55
|
-
- Add to DECISIONS.md if architectural choice made
|
|
56
|
-
|
|
57
|
-
════════════════════════════════════════════════════════════════
|
|
58
|
-
🔄 MULTI-AGENT MODE
|
|
59
|
-
════════════════════════════════════════════════════════════════
|
|
60
|
-
- Check PROJECT-STATE.md "In Progress" - dont duplicate work
|
|
61
|
-
- Add YOUR task to In Progress when starting
|
|
62
|
-
- If conflict → STOP and ask user
|
|
63
|
-
|
|
64
|
-
════════════════════════════════════════════════════════════════
|
|
65
|
-
💡 REMEMBER: Check existing code FIRST. Copy patterns. Validate.
|
|
66
|
-
════════════════════════════════════════════════════════════════'`
|
|
13
|
+
command: `echo '[CodeBakers] Loading project context...'`
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
PostToolUse: [
|
|
17
|
+
{
|
|
18
|
+
type: "command",
|
|
19
|
+
matcher: "Write|Edit",
|
|
20
|
+
command: `echo '[CodeBakers] Code written - remember to self-review before marking done'`
|
|
67
21
|
}
|
|
68
22
|
]
|
|
69
23
|
}
|
|
70
24
|
};
|
|
71
25
|
|
|
26
|
+
// Instructions that get injected into the system prompt
|
|
27
|
+
const CODEBAKERS_INSTRUCTIONS = `
|
|
28
|
+
<user-prompt-submit-hook>
|
|
29
|
+
[CodeBakers] Active - Follow these steps for EVERY request:
|
|
30
|
+
|
|
31
|
+
1. CONTEXT: Read CLAUDE.md, PROJECT-CONTEXT.md, PROJECT-STATE.md
|
|
32
|
+
2. PRE-FLIGHT: Check existing code patterns before writing new code
|
|
33
|
+
3. EXECUTE: Use patterns from .claude/ folder
|
|
34
|
+
4. SELF-REVIEW: Verify TypeScript compiles, imports resolve, error handling exists
|
|
35
|
+
5. UPDATE: Mark tasks complete in PROJECT-STATE.md
|
|
36
|
+
|
|
37
|
+
Output format: "[CodeBakers] Building [feature] using [patterns]"
|
|
38
|
+
</user-prompt-submit-hook>
|
|
39
|
+
`;
|
|
40
|
+
|
|
72
41
|
/**
|
|
73
42
|
* Install the CodeBakers hook into ~/.claude/settings.json
|
|
74
43
|
*/
|
|
@@ -117,23 +86,25 @@ export async function installHook(): Promise<void> {
|
|
|
117
86
|
}
|
|
118
87
|
}
|
|
119
88
|
|
|
120
|
-
// Merge
|
|
89
|
+
// Merge hooks into settings
|
|
121
90
|
settings.hooks = settings.hooks || {};
|
|
122
91
|
(settings.hooks as Record<string, unknown>).UserPromptSubmit = HOOK_TEMPLATE.hooks.UserPromptSubmit;
|
|
92
|
+
(settings.hooks as Record<string, unknown>).PostToolUse = HOOK_TEMPLATE.hooks.PostToolUse;
|
|
123
93
|
|
|
124
94
|
// Write back
|
|
125
95
|
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
126
96
|
|
|
127
97
|
spinner.succeed('Hook installed successfully!');
|
|
128
98
|
|
|
129
|
-
console.log(chalk.white('\n
|
|
130
|
-
console.log(chalk.
|
|
131
|
-
console.log(chalk.
|
|
132
|
-
|
|
133
|
-
console.log(chalk.
|
|
134
|
-
console.log(chalk.gray(' ✓
|
|
135
|
-
console.log(chalk.gray(' ✓
|
|
136
|
-
console.log(chalk.gray(' ✓
|
|
99
|
+
console.log(chalk.white('\n You\'ll see [CodeBakers] feedback in terminal:\n'));
|
|
100
|
+
console.log(chalk.cyan(' [CodeBakers] Loading project context...'));
|
|
101
|
+
console.log(chalk.cyan(' [CodeBakers] Code written - remember to self-review\n'));
|
|
102
|
+
|
|
103
|
+
console.log(chalk.white(' What happens automatically:\n'));
|
|
104
|
+
console.log(chalk.gray(' ✓ Loads project context before every response'));
|
|
105
|
+
console.log(chalk.gray(' ✓ Pre-flight checks before writing code'));
|
|
106
|
+
console.log(chalk.gray(' ✓ Self-review reminders after code changes'));
|
|
107
|
+
console.log(chalk.gray(' ✓ Pattern-based development from .claude/ folder\n'));
|
|
137
108
|
|
|
138
109
|
console.log(chalk.yellow(' ⚠️ Restart Claude Code for changes to take effect.\n'));
|
|
139
110
|
} catch (error) {
|
|
@@ -162,13 +133,18 @@ export async function uninstallHook(): Promise<void> {
|
|
|
162
133
|
|
|
163
134
|
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
164
135
|
|
|
165
|
-
if (!settings.hooks?.UserPromptSubmit) {
|
|
166
|
-
spinner.info('No
|
|
136
|
+
if (!settings.hooks?.UserPromptSubmit && !settings.hooks?.PostToolUse) {
|
|
137
|
+
spinner.info('No CodeBakers hooks found. Nothing to remove.');
|
|
167
138
|
return;
|
|
168
139
|
}
|
|
169
140
|
|
|
170
|
-
// Remove
|
|
171
|
-
|
|
141
|
+
// Remove both hooks
|
|
142
|
+
if (settings.hooks?.UserPromptSubmit) {
|
|
143
|
+
delete settings.hooks.UserPromptSubmit;
|
|
144
|
+
}
|
|
145
|
+
if (settings.hooks?.PostToolUse) {
|
|
146
|
+
delete settings.hooks.PostToolUse;
|
|
147
|
+
}
|
|
172
148
|
|
|
173
149
|
// Clean up empty hooks object
|
|
174
150
|
if (Object.keys(settings.hooks).length === 0) {
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { createInterface } from 'readline';
|
|
4
|
+
import { writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import * as templates from '../templates/nextjs-supabase.js';
|
|
8
|
+
|
|
9
|
+
async function prompt(question: string): Promise<string> {
|
|
10
|
+
const rl = createInterface({
|
|
11
|
+
input: process.stdin,
|
|
12
|
+
output: process.stdout,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
rl.question(question, (answer) => {
|
|
17
|
+
rl.close();
|
|
18
|
+
resolve(answer.trim());
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function confirm(question: string): Promise<boolean> {
|
|
24
|
+
const answer = await prompt(`${question} (Y/n): `);
|
|
25
|
+
return answer.toLowerCase() !== 'n';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Scaffold a new project with full structure
|
|
30
|
+
*/
|
|
31
|
+
export async function scaffold(): Promise<void> {
|
|
32
|
+
console.log(chalk.blue(`
|
|
33
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
34
|
+
║ ║
|
|
35
|
+
║ ${chalk.bold('CodeBakers Project Scaffolding')} ║
|
|
36
|
+
║ ║
|
|
37
|
+
║ Create a production-ready project in seconds ║
|
|
38
|
+
║ ║
|
|
39
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
40
|
+
`));
|
|
41
|
+
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
const files = readdirSync(cwd);
|
|
44
|
+
const hasFiles = files.filter(f => !f.startsWith('.')).length > 0;
|
|
45
|
+
|
|
46
|
+
if (hasFiles) {
|
|
47
|
+
console.log(chalk.yellow(' ⚠️ This directory is not empty.\n'));
|
|
48
|
+
const proceed = await confirm(' Continue anyway? (Existing files may be overwritten)');
|
|
49
|
+
if (!proceed) {
|
|
50
|
+
console.log(chalk.gray('\n Run this command in an empty directory.\n'));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Select stack
|
|
56
|
+
console.log(chalk.white('\n Select your stack:\n'));
|
|
57
|
+
console.log(chalk.gray(' 1. ') + chalk.cyan('Next.js + Supabase + Drizzle') + chalk.gray(' (Recommended)'));
|
|
58
|
+
console.log(chalk.gray(' 2. ') + chalk.cyan('Next.js + Prisma') + chalk.gray(' (Coming soon)'));
|
|
59
|
+
console.log(chalk.gray(' 3. ') + chalk.cyan('Express API') + chalk.gray(' (Coming soon)\n'));
|
|
60
|
+
|
|
61
|
+
let stackChoice = '';
|
|
62
|
+
while (!['1', '2', '3'].includes(stackChoice)) {
|
|
63
|
+
stackChoice = await prompt(' Enter 1, 2, or 3: ');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (stackChoice !== '1') {
|
|
67
|
+
console.log(chalk.yellow('\n That stack is coming soon! Using Next.js + Supabase + Drizzle.\n'));
|
|
68
|
+
stackChoice = '1';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get project name
|
|
72
|
+
const defaultName = cwd.split(/[\\/]/).pop() || 'my-project';
|
|
73
|
+
const projectName = await prompt(` Project name (${defaultName}): `) || defaultName;
|
|
74
|
+
|
|
75
|
+
console.log(chalk.green(`\n Creating ${projectName} with Next.js + Supabase + Drizzle...\n`));
|
|
76
|
+
|
|
77
|
+
// Create project structure
|
|
78
|
+
const spinner = ora(' Creating project structure...').start();
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// Create directories
|
|
82
|
+
const dirs = [
|
|
83
|
+
'src/app',
|
|
84
|
+
'src/components',
|
|
85
|
+
'src/lib/supabase',
|
|
86
|
+
'src/db',
|
|
87
|
+
'src/db/migrations',
|
|
88
|
+
'src/services',
|
|
89
|
+
'src/types',
|
|
90
|
+
'public',
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
for (const dir of dirs) {
|
|
94
|
+
const dirPath = join(cwd, dir);
|
|
95
|
+
if (!existsSync(dirPath)) {
|
|
96
|
+
mkdirSync(dirPath, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
spinner.text = ' Writing configuration files...';
|
|
101
|
+
|
|
102
|
+
// Write package.json
|
|
103
|
+
const packageJson = { ...templates.PACKAGE_JSON, name: projectName };
|
|
104
|
+
writeFileSync(join(cwd, 'package.json'), JSON.stringify(packageJson, null, 2));
|
|
105
|
+
|
|
106
|
+
// Write .env.example
|
|
107
|
+
writeFileSync(join(cwd, '.env.example'), templates.ENV_EXAMPLE);
|
|
108
|
+
writeFileSync(join(cwd, '.env.local'), templates.ENV_EXAMPLE);
|
|
109
|
+
|
|
110
|
+
// Write config files
|
|
111
|
+
writeFileSync(join(cwd, 'drizzle.config.ts'), templates.DRIZZLE_CONFIG);
|
|
112
|
+
writeFileSync(join(cwd, 'tailwind.config.ts'), templates.TAILWIND_CONFIG);
|
|
113
|
+
writeFileSync(join(cwd, 'postcss.config.mjs'), templates.POSTCSS_CONFIG);
|
|
114
|
+
writeFileSync(join(cwd, 'tsconfig.json'), JSON.stringify(templates.TSCONFIG, null, 2));
|
|
115
|
+
writeFileSync(join(cwd, 'next.config.ts'), templates.NEXT_CONFIG);
|
|
116
|
+
writeFileSync(join(cwd, '.gitignore'), templates.GITIGNORE);
|
|
117
|
+
|
|
118
|
+
spinner.text = ' Writing source files...';
|
|
119
|
+
|
|
120
|
+
// Write Supabase files
|
|
121
|
+
writeFileSync(join(cwd, 'src/lib/supabase/server.ts'), templates.SUPABASE_SERVER);
|
|
122
|
+
writeFileSync(join(cwd, 'src/lib/supabase/client.ts'), templates.SUPABASE_CLIENT);
|
|
123
|
+
writeFileSync(join(cwd, 'src/lib/supabase/middleware.ts'), templates.SUPABASE_MIDDLEWARE);
|
|
124
|
+
|
|
125
|
+
// Write middleware
|
|
126
|
+
writeFileSync(join(cwd, 'middleware.ts'), templates.MIDDLEWARE);
|
|
127
|
+
|
|
128
|
+
// Write database files
|
|
129
|
+
writeFileSync(join(cwd, 'src/db/schema.ts'), templates.DB_SCHEMA);
|
|
130
|
+
writeFileSync(join(cwd, 'src/db/index.ts'), templates.DB_INDEX);
|
|
131
|
+
|
|
132
|
+
// Write app files
|
|
133
|
+
writeFileSync(join(cwd, 'src/app/globals.css'), templates.GLOBALS_CSS);
|
|
134
|
+
writeFileSync(join(cwd, 'src/app/layout.tsx'), templates.LAYOUT_TSX);
|
|
135
|
+
writeFileSync(join(cwd, 'src/app/page.tsx'), templates.PAGE_TSX);
|
|
136
|
+
|
|
137
|
+
// Write utils
|
|
138
|
+
writeFileSync(join(cwd, 'src/lib/utils.ts'), templates.UTILS_CN);
|
|
139
|
+
|
|
140
|
+
spinner.succeed('Project structure created!');
|
|
141
|
+
|
|
142
|
+
// Ask about installing dependencies
|
|
143
|
+
console.log('');
|
|
144
|
+
const installDeps = await confirm(' Install dependencies with npm?');
|
|
145
|
+
|
|
146
|
+
if (installDeps) {
|
|
147
|
+
const installSpinner = ora(' Installing dependencies (this may take a minute)...').start();
|
|
148
|
+
try {
|
|
149
|
+
execSync('npm install', { cwd, stdio: 'pipe' });
|
|
150
|
+
installSpinner.succeed('Dependencies installed!');
|
|
151
|
+
} catch (error) {
|
|
152
|
+
installSpinner.warn('Could not install dependencies automatically');
|
|
153
|
+
console.log(chalk.gray(' Run `npm install` manually.\n'));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Success message
|
|
158
|
+
console.log(chalk.green(`
|
|
159
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
160
|
+
║ ║
|
|
161
|
+
║ ${chalk.bold('✓ Project scaffolded successfully!')} ║
|
|
162
|
+
║ ║
|
|
163
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
164
|
+
`));
|
|
165
|
+
|
|
166
|
+
console.log(chalk.white(' Project structure:\n'));
|
|
167
|
+
console.log(chalk.gray(' src/'));
|
|
168
|
+
console.log(chalk.gray(' ├── app/ ') + chalk.cyan('← Pages & layouts'));
|
|
169
|
+
console.log(chalk.gray(' ├── components/ ') + chalk.cyan('← React components'));
|
|
170
|
+
console.log(chalk.gray(' ├── lib/ ') + chalk.cyan('← Utilities & clients'));
|
|
171
|
+
console.log(chalk.gray(' │ └── supabase/ ') + chalk.cyan('← Supabase clients (ready!)'));
|
|
172
|
+
console.log(chalk.gray(' ├── db/ ') + chalk.cyan('← Database schema & queries'));
|
|
173
|
+
console.log(chalk.gray(' ├── services/ ') + chalk.cyan('← Business logic'));
|
|
174
|
+
console.log(chalk.gray(' └── types/ ') + chalk.cyan('← TypeScript types'));
|
|
175
|
+
console.log('');
|
|
176
|
+
|
|
177
|
+
console.log(chalk.white(' Next steps:\n'));
|
|
178
|
+
console.log(chalk.cyan(' 1. ') + chalk.gray('Update .env.local with your Supabase credentials'));
|
|
179
|
+
console.log(chalk.cyan(' 2. ') + chalk.gray('Run `npm run dev` to start development'));
|
|
180
|
+
console.log(chalk.cyan(' 3. ') + chalk.gray('Run `codebakers init` to add CodeBakers patterns'));
|
|
181
|
+
console.log(chalk.cyan(' 4. ') + chalk.gray('Start building with AI assistance!\n'));
|
|
182
|
+
|
|
183
|
+
console.log(chalk.white(' Supabase setup:\n'));
|
|
184
|
+
console.log(chalk.gray(' 1. Create a project at https://supabase.com'));
|
|
185
|
+
console.log(chalk.gray(' 2. Go to Settings → API'));
|
|
186
|
+
console.log(chalk.gray(' 3. Copy URL and anon key to .env.local'));
|
|
187
|
+
console.log(chalk.gray(' 4. Go to Settings → Database → Connection string'));
|
|
188
|
+
console.log(chalk.gray(' 5. Copy DATABASE_URL to .env.local\n'));
|
|
189
|
+
|
|
190
|
+
} catch (error) {
|
|
191
|
+
spinner.fail('Project scaffolding failed');
|
|
192
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
193
|
+
console.log(chalk.red(`\n Error: ${message}\n`));
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import { createInterface } from 'readline';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
4
5
|
import { setApiKey, getApiKey, getApiUrl } from '../config.js';
|
|
5
6
|
|
|
6
7
|
function prompt(question: string): Promise<string> {
|
|
@@ -83,29 +84,36 @@ function showFinalInstructions(): void {
|
|
|
83
84
|
|
|
84
85
|
console.log(chalk.green('\n ✅ API key saved!\n'));
|
|
85
86
|
console.log(chalk.blue(' ══════════════════════════════════════════════════════════'));
|
|
86
|
-
console.log(chalk.white.bold('\n STEP 2:
|
|
87
|
+
console.log(chalk.white.bold('\n STEP 2: Connecting CodeBakers to Claude...\n'));
|
|
87
88
|
console.log(chalk.blue(' ══════════════════════════════════════════════════════════\n'));
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const terminalCmd = isWindows
|
|
90
|
+
// Auto-install MCP server
|
|
91
|
+
const mcpCmd = isWindows
|
|
92
92
|
? 'claude mcp add --transport stdio codebakers -- cmd /c npx -y @codebakers/cli serve'
|
|
93
93
|
: 'claude mcp add --transport stdio codebakers -- npx -y @codebakers/cli serve';
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
95
|
+
try {
|
|
96
|
+
execSync(mcpCmd, { stdio: 'pipe' });
|
|
97
|
+
console.log(chalk.green(' ✅ CodeBakers MCP server installed!\n'));
|
|
98
|
+
} catch (error) {
|
|
99
|
+
// Check if it's already installed (command might fail if already exists)
|
|
100
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
101
|
+
if (errorMessage.includes('already exists') || errorMessage.includes('already registered')) {
|
|
102
|
+
console.log(chalk.green(' ✅ CodeBakers MCP server already installed!\n'));
|
|
103
|
+
} else {
|
|
104
|
+
console.log(chalk.yellow(' ⚠️ Could not auto-install MCP server.\n'));
|
|
105
|
+
console.log(chalk.white(' Run this command manually in your terminal:\n'));
|
|
106
|
+
console.log(chalk.bgBlue.white('\n ' + mcpCmd + ' \n'));
|
|
107
|
+
console.log(chalk.gray('\n Then restart Claude Code.\n'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
103
111
|
|
|
104
112
|
console.log(chalk.blue(' ══════════════════════════════════════════════════════════'));
|
|
105
|
-
console.log(chalk.white.bold('\n
|
|
113
|
+
console.log(chalk.white.bold('\n 🎉 Setup Complete!\n'));
|
|
106
114
|
console.log(chalk.blue(' ══════════════════════════════════════════════════════════\n'));
|
|
107
115
|
|
|
108
|
-
console.log(chalk.white('
|
|
116
|
+
console.log(chalk.white(' CodeBakers is now ready. Try this prompt:\n'));
|
|
109
117
|
console.log(chalk.cyan(' "Build a login form with email validation"\n'));
|
|
110
118
|
|
|
111
119
|
console.log(chalk.gray(' Claude will now use CodeBakers patterns automatically.\n'));
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { init } from './commands/init.js';
|
|
|
11
11
|
import { serve } from './commands/serve.js';
|
|
12
12
|
import { mcpConfig, mcpUninstall } from './commands/mcp-config.js';
|
|
13
13
|
import { setup } from './commands/setup.js';
|
|
14
|
+
import { scaffold } from './commands/scaffold.js';
|
|
14
15
|
|
|
15
16
|
const program = new Command();
|
|
16
17
|
|
|
@@ -30,6 +31,12 @@ program
|
|
|
30
31
|
.description('Interactive project setup wizard')
|
|
31
32
|
.action(init);
|
|
32
33
|
|
|
34
|
+
program
|
|
35
|
+
.command('scaffold')
|
|
36
|
+
.alias('new')
|
|
37
|
+
.description('Create a new project with full stack scaffolding (Next.js + Supabase + Drizzle)')
|
|
38
|
+
.action(scaffold);
|
|
39
|
+
|
|
33
40
|
program
|
|
34
41
|
.command('login')
|
|
35
42
|
.description('Login with your API key')
|