ai-flow-dev 1.0.3 → 1.1.2
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 +60 -35
- package/dist/cli.js +204 -236
- package/dist/cli.js.map +1 -1
- package/dist/fs-utils.js +3 -39
- package/dist/fs-utils.js.map +1 -1
- package/package.json +11 -12
- package/prompts/backend/{flow-docs-gen-phase-7.md → flow-bootstrap-phase-7.md} +41 -108
- package/prompts/backend/flow-bootstrap-phase-8.md +911 -0
- package/prompts/backend/{flow-project-roadmap.md → flow-bootstrap-phase-9.md} +255 -344
- package/prompts/backend/{flow-docs-gen.md → flow-bootstrap.md} +102 -37
- package/prompts/frontend/{flow-docs-gen-phase-0.md → flow-bootstrap-phase-0.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-1.md → flow-bootstrap-phase-1.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-3.md → flow-bootstrap-phase-3.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-4.md → flow-bootstrap-phase-4.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-5.md → flow-bootstrap-phase-5.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-6.md → flow-bootstrap-phase-6.md} +2 -1
- package/prompts/frontend/{flow-docs-gen-phase-7.md → flow-bootstrap-phase-7.md} +225 -200
- package/prompts/frontend/flow-bootstrap-phase-8.md +670 -0
- package/prompts/frontend/{flow-docs-gen.md → flow-bootstrap.md} +47 -20
- package/prompts/frontend/flow-docs-sync.md +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-0.md → flow-bootstrap-phase-0.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-1.md → flow-bootstrap-phase-1.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-2.md → flow-bootstrap-phase-2.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-3.md → flow-bootstrap-phase-3.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-4.md → flow-bootstrap-phase-4.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-5.md → flow-bootstrap-phase-5.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-6.md → flow-bootstrap-phase-6.md} +2 -1
- package/prompts/mobile/{flow-docs-gen-phase-7.md → flow-bootstrap-phase-7.md} +174 -132
- package/prompts/mobile/flow-bootstrap-phase-8.md +676 -0
- package/prompts/mobile/{flow-docs-gen.md → flow-bootstrap.md} +47 -20
- package/prompts/mobile/flow-docs-sync.md +2 -1
- package/templates/shared/AGENT.template.md +1 -1
- package/prompts/backend/flow-project-init.md +0 -332
- /package/prompts/backend/{flow-docs-gen-phase-0.md → flow-bootstrap-phase-0.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-1.md → flow-bootstrap-phase-1.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-2.md → flow-bootstrap-phase-2.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-3.md → flow-bootstrap-phase-3.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-4.md → flow-bootstrap-phase-4.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-5.md → flow-bootstrap-phase-5.md} +0 -0
- /package/prompts/backend/{flow-docs-gen-phase-6.md → flow-bootstrap-phase-6.md} +0 -0
- /package/prompts/frontend/{flow-docs-gen-phase-2.md → flow-bootstrap-phase-2.md} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,52 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
-
};
|
|
39
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
const commander_1 = require("commander");
|
|
41
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
-
const ora_1 = __importDefault(require("ora"));
|
|
44
|
-
const fs = __importStar(require("fs-extra"));
|
|
45
|
-
const path = __importStar(require("path"));
|
|
46
|
-
const ejs_1 = __importDefault(require("ejs"));
|
|
47
|
-
const fs_utils_1 = require("./fs-utils");
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname } from 'path';
|
|
10
|
+
import ejs from 'ejs';
|
|
11
|
+
import { assertDirWritable } from './fs-utils.js';
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
48
14
|
const ROOT_DIR = path.resolve(__dirname, '..');
|
|
49
|
-
const program = new
|
|
15
|
+
const program = new Command();
|
|
50
16
|
const AI_TOOLS = [
|
|
51
17
|
{
|
|
52
18
|
name: 'GitHub Copilot',
|
|
@@ -74,7 +40,10 @@ const AI_TOOLS = [
|
|
|
74
40
|
description: '',
|
|
75
41
|
},
|
|
76
42
|
];
|
|
77
|
-
|
|
43
|
+
// Read package.json for version
|
|
44
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
45
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
46
|
+
const PKG_VERSION = packageJson.version;
|
|
78
47
|
const EXIT = {
|
|
79
48
|
OK: 0,
|
|
80
49
|
INVALID_ARGS: 2,
|
|
@@ -82,7 +51,7 @@ const EXIT = {
|
|
|
82
51
|
};
|
|
83
52
|
function logVerbose(message, verbose) {
|
|
84
53
|
if (verbose)
|
|
85
|
-
console.log(
|
|
54
|
+
console.log(chalk.gray(message));
|
|
86
55
|
}
|
|
87
56
|
function isValidName(value) {
|
|
88
57
|
const v = value.trim();
|
|
@@ -106,8 +75,8 @@ async function selectAITool(providedTool) {
|
|
|
106
75
|
if (providedTool) {
|
|
107
76
|
const tool = AI_TOOLS.find((t) => t.value === providedTool);
|
|
108
77
|
if (!tool) {
|
|
109
|
-
console.error(
|
|
110
|
-
console.log(
|
|
78
|
+
console.error(chalk.red(`❌ Invalid AI tool: ${providedTool}`));
|
|
79
|
+
console.log(chalk.yellow('Available options: claude, cursor, copilot, gemini, all'));
|
|
111
80
|
process.exit(EXIT.INVALID_ARGS);
|
|
112
81
|
}
|
|
113
82
|
return providedTool === 'all'
|
|
@@ -116,64 +85,63 @@ async function selectAITool(providedTool) {
|
|
|
116
85
|
}
|
|
117
86
|
// Display banner
|
|
118
87
|
console.log('\n');
|
|
119
|
-
console.log(
|
|
120
|
-
console.log(
|
|
88
|
+
console.log(chalk.cyan(' ╔═══════════════════════════════════════════════════════════════════╗'));
|
|
89
|
+
console.log(chalk.cyan(' ║') +
|
|
121
90
|
' ' +
|
|
122
|
-
|
|
123
|
-
console.log(
|
|
124
|
-
|
|
91
|
+
chalk.cyan('║'));
|
|
92
|
+
console.log(chalk.cyan(' ║') +
|
|
93
|
+
chalk.bold.cyan(' █████╗ ██╗ ███████╗██╗ ██████╗ ██╗ ██╗') +
|
|
125
94
|
' ' +
|
|
126
|
-
|
|
127
|
-
console.log(
|
|
128
|
-
|
|
95
|
+
chalk.cyan('║'));
|
|
96
|
+
console.log(chalk.cyan(' ║') +
|
|
97
|
+
chalk.bold.cyan(' ██╔══██╗██║ ██╔════╝██║ ██╔═══██╗██║ ██║') +
|
|
129
98
|
' ' +
|
|
130
|
-
|
|
131
|
-
console.log(
|
|
132
|
-
|
|
99
|
+
chalk.cyan('║'));
|
|
100
|
+
console.log(chalk.cyan(' ║') +
|
|
101
|
+
chalk.bold.cyan(' ███████║██║ █████╗ ██║ ██║ ██║██║ █╗ ██║') +
|
|
133
102
|
' ' +
|
|
134
|
-
|
|
135
|
-
console.log(
|
|
136
|
-
|
|
103
|
+
chalk.cyan('║'));
|
|
104
|
+
console.log(chalk.cyan(' ║') +
|
|
105
|
+
chalk.bold.cyan(' ██╔══██║██║ ██╔══╝ ██║ ██║ ██║██║███╗██║') +
|
|
137
106
|
' ' +
|
|
138
|
-
|
|
139
|
-
console.log(
|
|
140
|
-
|
|
107
|
+
chalk.cyan('║'));
|
|
108
|
+
console.log(chalk.cyan(' ║') +
|
|
109
|
+
chalk.bold.cyan(' ██║ ██║██║ ██║ ███████╗╚██████╔╝╚███╔███╔╝') +
|
|
141
110
|
' ' +
|
|
142
|
-
|
|
143
|
-
console.log(
|
|
144
|
-
|
|
111
|
+
chalk.cyan('║'));
|
|
112
|
+
console.log(chalk.cyan(' ║') +
|
|
113
|
+
chalk.cyan(' ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝') +
|
|
145
114
|
' ' +
|
|
146
|
-
|
|
147
|
-
console.log(
|
|
115
|
+
chalk.cyan('║'));
|
|
116
|
+
console.log(chalk.cyan(' ║') +
|
|
148
117
|
' ' +
|
|
149
|
-
|
|
150
|
-
console.log(
|
|
118
|
+
chalk.cyan('║'));
|
|
119
|
+
console.log(chalk.cyan(' ║') +
|
|
151
120
|
' ' +
|
|
152
|
-
|
|
121
|
+
chalk.white('✨ From Idea to Production with AI Guidance') +
|
|
153
122
|
' ' +
|
|
154
|
-
|
|
155
|
-
console.log(
|
|
123
|
+
chalk.cyan('║'));
|
|
124
|
+
console.log(chalk.cyan(' ║') +
|
|
156
125
|
' ' +
|
|
157
|
-
|
|
158
|
-
console.log(
|
|
126
|
+
chalk.cyan('║'));
|
|
127
|
+
console.log(chalk.cyan(' ╚═══════════════════════════════════════════════════════════════════╝'));
|
|
159
128
|
console.log('\n');
|
|
160
|
-
console.log(
|
|
161
|
-
console.log(
|
|
162
|
-
console.log(
|
|
163
|
-
console.log(
|
|
129
|
+
console.log(chalk.white(' 📂 Project Setup'));
|
|
130
|
+
console.log(chalk.gray(' ────────────────────────────────────────────────────────────────────'));
|
|
131
|
+
console.log(chalk.gray(` Working Directory: ${process.cwd()}`));
|
|
132
|
+
console.log(chalk.gray(` Version: ${PKG_VERSION}`));
|
|
164
133
|
console.log('\n');
|
|
165
|
-
console.log(
|
|
166
|
-
console.log(
|
|
167
|
-
const { selectedTool } = await
|
|
134
|
+
console.log(chalk.white(' 🤖 Select your AI development tool:'));
|
|
135
|
+
console.log(chalk.gray(' ────────────────────────────────────────────────────────────────────'));
|
|
136
|
+
const { selectedTool } = await inquirer.prompt([
|
|
168
137
|
{
|
|
169
|
-
type: '
|
|
138
|
+
type: 'rawlist',
|
|
170
139
|
name: 'selectedTool',
|
|
171
|
-
message: '
|
|
140
|
+
message: 'Select your AI tool:',
|
|
172
141
|
choices: AI_TOOLS.map((tool) => ({
|
|
173
|
-
name:
|
|
142
|
+
name: tool.name,
|
|
174
143
|
value: tool.value,
|
|
175
144
|
})),
|
|
176
|
-
pageSize: 10,
|
|
177
145
|
},
|
|
178
146
|
]);
|
|
179
147
|
return selectedTool === 'all'
|
|
@@ -185,8 +153,8 @@ async function selectProjectType(providedType) {
|
|
|
185
153
|
if (providedType) {
|
|
186
154
|
const valid = ['backend', 'frontend', 'fullstack', 'mobile'];
|
|
187
155
|
if (!valid.includes(providedType)) {
|
|
188
|
-
console.error(
|
|
189
|
-
console.log(
|
|
156
|
+
console.error(chalk.red(`❌ Invalid project type: ${providedType}`));
|
|
157
|
+
console.log(chalk.yellow('Available options: backend, frontend, fullstack, mobile'));
|
|
190
158
|
process.exit(EXIT.INVALID_ARGS);
|
|
191
159
|
}
|
|
192
160
|
return providedType;
|
|
@@ -197,7 +165,7 @@ async function selectProjectType(providedType) {
|
|
|
197
165
|
return 'backend';
|
|
198
166
|
}
|
|
199
167
|
// v1.4.0: Interactive selection for backend/frontend/fullstack/mobile
|
|
200
|
-
const answer = await
|
|
168
|
+
const answer = await inquirer.prompt([
|
|
201
169
|
{
|
|
202
170
|
type: 'list',
|
|
203
171
|
name: 'projectType',
|
|
@@ -217,7 +185,7 @@ async function checkIfInitialized(targetPath) {
|
|
|
217
185
|
return await fs.pathExists(bootstrapPath);
|
|
218
186
|
}
|
|
219
187
|
async function createBootstrapStructure(targetPath, aiTools, projectType = 'backend', dryRun, verbose) {
|
|
220
|
-
const spinner = (
|
|
188
|
+
const spinner = ora('Creating .ai-flow structure...').start();
|
|
221
189
|
try {
|
|
222
190
|
const bootstrapPath = path.join(targetPath, '.ai-flow');
|
|
223
191
|
// Create core directories
|
|
@@ -225,7 +193,7 @@ async function createBootstrapStructure(targetPath, aiTools, projectType = 'back
|
|
|
225
193
|
spinner.succeed('Created .ai-flow structure (dry-run)');
|
|
226
194
|
return;
|
|
227
195
|
}
|
|
228
|
-
await
|
|
196
|
+
await assertDirWritable(targetPath);
|
|
229
197
|
await fs.ensureDir(path.join(bootstrapPath, 'core'));
|
|
230
198
|
await fs.ensureDir(path.join(bootstrapPath, 'prompts'));
|
|
231
199
|
await fs.ensureDir(path.join(bootstrapPath, 'templates', 'docs'));
|
|
@@ -251,14 +219,14 @@ async function createBootstrapStructure(targetPath, aiTools, projectType = 'back
|
|
|
251
219
|
}
|
|
252
220
|
}
|
|
253
221
|
async function renderTemplates(targetPath, projectData, projectType = 'backend', aiTools = [], dryRun, verbose) {
|
|
254
|
-
const spinner = (
|
|
222
|
+
const spinner = ora('Generating documentation from templates...').start();
|
|
255
223
|
try {
|
|
256
224
|
const templatesTarget = path.join(targetPath, '.ai-flow', 'templates');
|
|
257
225
|
if (dryRun) {
|
|
258
226
|
spinner.succeed('Documentation generated from templates (dry-run)');
|
|
259
227
|
return;
|
|
260
228
|
}
|
|
261
|
-
await
|
|
229
|
+
await assertDirWritable(templatesTarget);
|
|
262
230
|
await fs.ensureDir(templatesTarget);
|
|
263
231
|
// Find all .template.md and .template files in a directory and subfolders
|
|
264
232
|
const walk = async (dir) => {
|
|
@@ -350,7 +318,7 @@ async function renderTemplates(targetPath, projectData, projectType = 'backend',
|
|
|
350
318
|
await fs.ensureDir(path.dirname(destPath));
|
|
351
319
|
const templateContent = await fs.readFile(templateFile, 'utf8');
|
|
352
320
|
// Render with EJS, leaving {{PLACEHOLDER}} for everything except name/description
|
|
353
|
-
const rendered =
|
|
321
|
+
const rendered = ejs.render(templateContent, {
|
|
354
322
|
PROJECT_NAME: projectData.name,
|
|
355
323
|
PROJECT_DESCRIPTION: projectData.description,
|
|
356
324
|
PROJECT_TYPE: projectType,
|
|
@@ -368,7 +336,7 @@ async function renderTemplates(targetPath, projectData, projectType = 'backend',
|
|
|
368
336
|
}
|
|
369
337
|
}
|
|
370
338
|
async function copyPrompts(targetPath, dryRun, verbose) {
|
|
371
|
-
const spinner = (
|
|
339
|
+
const spinner = ora('Copying master prompts...').start();
|
|
372
340
|
try {
|
|
373
341
|
const promptsSource = path.join(ROOT_DIR, 'prompts');
|
|
374
342
|
const promptsTarget = path.join(targetPath, '.ai-flow', 'prompts');
|
|
@@ -376,7 +344,7 @@ async function copyPrompts(targetPath, dryRun, verbose) {
|
|
|
376
344
|
spinner.succeed('Master prompts copied (dry-run)');
|
|
377
345
|
return;
|
|
378
346
|
}
|
|
379
|
-
await
|
|
347
|
+
await assertDirWritable(promptsTarget);
|
|
380
348
|
await fs.copy(promptsSource, promptsTarget);
|
|
381
349
|
logVerbose(`Copied prompts to ${promptsTarget}`, verbose);
|
|
382
350
|
spinner.succeed('Master prompts copied');
|
|
@@ -387,7 +355,7 @@ async function copyPrompts(targetPath, dryRun, verbose) {
|
|
|
387
355
|
}
|
|
388
356
|
}
|
|
389
357
|
async function setupSlashCommands(targetPath, aiTools, projectType = 'backend', dryRun, verbose) {
|
|
390
|
-
const spinner = (
|
|
358
|
+
const spinner = ora('Setting up slash commands...').start();
|
|
391
359
|
try {
|
|
392
360
|
// Determine which prompt directories to copy from
|
|
393
361
|
const promptSources = [];
|
|
@@ -415,7 +383,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
415
383
|
// Copilot: prompts in .github/prompts with .prompt.md suffix
|
|
416
384
|
const promptsTarget = path.join(targetPath, '.github', 'prompts');
|
|
417
385
|
if (!dryRun) {
|
|
418
|
-
await
|
|
386
|
+
await assertDirWritable(promptsTarget);
|
|
419
387
|
await fs.ensureDir(promptsTarget);
|
|
420
388
|
}
|
|
421
389
|
for (const file of files) {
|
|
@@ -433,7 +401,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
433
401
|
else if (tool === 'claude') {
|
|
434
402
|
const commandsTarget = path.join(targetPath, '.claude', 'commands');
|
|
435
403
|
if (!dryRun) {
|
|
436
|
-
await
|
|
404
|
+
await assertDirWritable(commandsTarget);
|
|
437
405
|
await fs.ensureDir(commandsTarget);
|
|
438
406
|
}
|
|
439
407
|
for (const file of files) {
|
|
@@ -448,7 +416,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
448
416
|
else if (tool === 'cursor') {
|
|
449
417
|
const commandsTarget = path.join(targetPath, '.cursor', 'commands');
|
|
450
418
|
if (!dryRun) {
|
|
451
|
-
await
|
|
419
|
+
await assertDirWritable(commandsTarget);
|
|
452
420
|
await fs.ensureDir(commandsTarget);
|
|
453
421
|
}
|
|
454
422
|
for (const file of files) {
|
|
@@ -463,7 +431,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
463
431
|
else if (tool === 'gemini') {
|
|
464
432
|
const commandsTarget = path.join(targetPath, '.gemini', 'commands');
|
|
465
433
|
if (!dryRun) {
|
|
466
|
-
await
|
|
434
|
+
await assertDirWritable(commandsTarget);
|
|
467
435
|
await fs.ensureDir(commandsTarget);
|
|
468
436
|
}
|
|
469
437
|
for (const file of files) {
|
|
@@ -489,8 +457,8 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
489
457
|
// Check if already initialized
|
|
490
458
|
const isInitialized = await checkIfInitialized(targetPath);
|
|
491
459
|
if (isInitialized) {
|
|
492
|
-
console.log(
|
|
493
|
-
const { reinitialize } = await
|
|
460
|
+
console.log(chalk.yellow('\n⚠️ Project already initialized with AI Flow'));
|
|
461
|
+
const { reinitialize } = await inquirer.prompt([
|
|
494
462
|
{
|
|
495
463
|
type: 'confirm',
|
|
496
464
|
name: 'reinitialize',
|
|
@@ -499,7 +467,7 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
499
467
|
},
|
|
500
468
|
]);
|
|
501
469
|
if (!reinitialize) {
|
|
502
|
-
console.log(
|
|
470
|
+
console.log(chalk.blue('Initialization cancelled'));
|
|
503
471
|
return;
|
|
504
472
|
}
|
|
505
473
|
}
|
|
@@ -515,17 +483,17 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
515
483
|
.join(' ');
|
|
516
484
|
// Request minimal project data only if not provided
|
|
517
485
|
if (projectName && !isValidName(projectName)) {
|
|
518
|
-
console.error(
|
|
486
|
+
console.error(chalk.red('Invalid project name'));
|
|
519
487
|
process.exit(EXIT.INVALID_ARGS);
|
|
520
488
|
}
|
|
521
489
|
if (projectDescription && !isValidDescription(projectDescription)) {
|
|
522
|
-
console.error(
|
|
490
|
+
console.error(chalk.red('Invalid project description'));
|
|
523
491
|
process.exit(EXIT.INVALID_ARGS);
|
|
524
492
|
}
|
|
525
493
|
let finalProjectName = projectName;
|
|
526
|
-
let finalProjectDescription = projectDescription || 'TBD - Run /flow-
|
|
494
|
+
let finalProjectDescription = projectDescription || 'TBD - Run /flow-bootstrap to define';
|
|
527
495
|
if (!finalProjectName) {
|
|
528
|
-
const answers = await
|
|
496
|
+
const answers = await inquirer.prompt([
|
|
529
497
|
{
|
|
530
498
|
type: 'input',
|
|
531
499
|
name: 'projectName',
|
|
@@ -537,141 +505,141 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
537
505
|
]);
|
|
538
506
|
finalProjectName = answers.projectName;
|
|
539
507
|
}
|
|
540
|
-
console.log(
|
|
508
|
+
console.log(chalk.cyan('\n📦 Initializing AI Flow...\n'));
|
|
541
509
|
// Create structure
|
|
542
510
|
await createBootstrapStructure(targetPath, aiTools, selectedProjectType, flags?.dryRun, flags?.verbose);
|
|
543
511
|
await renderTemplates(targetPath, { name: finalProjectName, description: finalProjectDescription }, selectedProjectType, aiTools, flags?.dryRun, flags?.verbose);
|
|
544
512
|
await copyPrompts(targetPath, flags?.dryRun, flags?.verbose);
|
|
545
513
|
await setupSlashCommands(targetPath, aiTools, selectedProjectType, flags?.dryRun, flags?.verbose);
|
|
546
514
|
const modeText = flags?.dryRun ? 'DRY-RUN' : 'WRITE';
|
|
547
|
-
console.log(
|
|
548
|
-
console.log(
|
|
549
|
-
console.log(
|
|
550
|
-
console.log(
|
|
551
|
-
console.log(
|
|
552
|
-
console.log(
|
|
553
|
-
console.log(
|
|
554
|
-
console.log(
|
|
515
|
+
console.log(chalk.green('\n✅ AI Flow initialized successfully!'));
|
|
516
|
+
console.log(chalk.white('\nSummary:'));
|
|
517
|
+
console.log(chalk.gray(` Project: ${finalProjectName}`));
|
|
518
|
+
console.log(chalk.gray(` Version: ${PKG_VERSION}`));
|
|
519
|
+
console.log(chalk.gray(` Directory: ${targetPath}`));
|
|
520
|
+
console.log(chalk.gray(` Tools: ${aiTools.join(', ')}`));
|
|
521
|
+
console.log(chalk.gray(` Mode: ${modeText}`));
|
|
522
|
+
console.log(chalk.white('\nNext steps:\n'));
|
|
555
523
|
const toolsText = aiTools.length === 1
|
|
556
524
|
? aiTools[0]
|
|
557
525
|
: `${aiTools.slice(0, -1).join(', ')} and ${aiTools[aiTools.length - 1]}`;
|
|
558
526
|
if (selectedProjectType === 'fullstack') {
|
|
559
527
|
if (aiTools.includes('claude')) {
|
|
560
|
-
console.log(
|
|
561
|
-
console.log(
|
|
562
|
-
console.log(
|
|
563
|
-
console.log(
|
|
528
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
529
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
530
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
531
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
564
532
|
}
|
|
565
533
|
else if (aiTools.includes('cursor')) {
|
|
566
|
-
console.log(
|
|
567
|
-
console.log(
|
|
568
|
-
console.log(
|
|
569
|
-
console.log(
|
|
534
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
535
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
536
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
537
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
570
538
|
}
|
|
571
539
|
else {
|
|
572
|
-
console.log(
|
|
573
|
-
console.log(
|
|
574
|
-
console.log(
|
|
575
|
-
console.log(
|
|
540
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
541
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
542
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
543
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
576
544
|
}
|
|
577
|
-
console.log(
|
|
578
|
-
console.log(
|
|
579
|
-
console.log(
|
|
580
|
-
console.log(
|
|
581
|
-
console.log(
|
|
582
|
-
console.log(
|
|
583
|
-
console.log(
|
|
584
|
-
console.log(
|
|
585
|
-
console.log(
|
|
586
|
-
console.log(
|
|
587
|
-
console.log(
|
|
588
|
-
console.log(
|
|
589
|
-
console.log(
|
|
590
|
-
console.log(
|
|
591
|
-
console.log(
|
|
592
|
-
console.log(
|
|
593
|
-
console.log(
|
|
594
|
-
console.log(
|
|
595
|
-
console.log(
|
|
596
|
-
console.log(
|
|
597
|
-
console.log(
|
|
598
|
-
console.log(
|
|
599
|
-
console.log(
|
|
545
|
+
console.log(chalk.white('Available slash commands:'));
|
|
546
|
+
console.log(chalk.gray(' Backend commands:'));
|
|
547
|
+
console.log(chalk.gray(' /backend-flow-bootstrap - Backend 7-phase documentation generation'));
|
|
548
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-0-context - Backend context discovery'));
|
|
549
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-1-business - Backend discovery & business'));
|
|
550
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-2-data - Backend data architecture'));
|
|
551
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-3-architecture - Backend system architecture'));
|
|
552
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-4-security - Backend security & auth'));
|
|
553
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-5-standards - Backend code standards'));
|
|
554
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-6-testing - Backend testing'));
|
|
555
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-7-operations - Backend operations + tools'));
|
|
556
|
+
console.log(chalk.gray(' /backend-flow-docs-sync - Update backend documentation\n'));
|
|
557
|
+
console.log(chalk.gray(' Frontend commands:'));
|
|
558
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap - Frontend 7-phase documentation generation'));
|
|
559
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-0-context - Frontend context discovery'));
|
|
560
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-1-discovery - Frontend discovery & UX'));
|
|
561
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-2-components - Frontend components & framework'));
|
|
562
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-3-state - Frontend state management'));
|
|
563
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-4-styling - Frontend styling & design'));
|
|
564
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-5-standards - Frontend code standards'));
|
|
565
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-6-testing - Frontend testing'));
|
|
566
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-7-deployment - Frontend deployment'));
|
|
567
|
+
console.log(chalk.gray(' /frontend-flow-docs-sync - Update frontend documentation\n'));
|
|
600
568
|
}
|
|
601
569
|
else if (selectedProjectType === 'mobile') {
|
|
602
570
|
if (aiTools.includes('claude')) {
|
|
603
|
-
console.log(
|
|
604
|
-
console.log(
|
|
605
|
-
console.log(
|
|
571
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
572
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
573
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
606
574
|
}
|
|
607
575
|
else if (aiTools.includes('cursor')) {
|
|
608
|
-
console.log(
|
|
609
|
-
console.log(
|
|
610
|
-
console.log(
|
|
576
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
577
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
578
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
611
579
|
}
|
|
612
580
|
else {
|
|
613
|
-
console.log(
|
|
614
|
-
console.log(
|
|
615
|
-
console.log(
|
|
581
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
582
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
583
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
616
584
|
}
|
|
617
|
-
console.log(
|
|
618
|
-
console.log(
|
|
619
|
-
console.log(
|
|
620
|
-
console.log(
|
|
621
|
-
console.log(
|
|
622
|
-
console.log(
|
|
623
|
-
console.log(
|
|
624
|
-
console.log(
|
|
625
|
-
console.log(
|
|
626
|
-
console.log(
|
|
627
|
-
console.log(
|
|
585
|
+
console.log(chalk.white('Available slash commands:'));
|
|
586
|
+
console.log(chalk.gray(' /flow-bootstrap - Full 7-phase documentation generation'));
|
|
587
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-0-context - Context Discovery (existing projects)'));
|
|
588
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-platform - Platform & Framework Selection'));
|
|
589
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-navigation - Navigation & Architecture'));
|
|
590
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-state - State & Data Management'));
|
|
591
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-permissions - Permissions & Native Features'));
|
|
592
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
593
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing Strategy'));
|
|
594
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-deployment - Store Deployment'));
|
|
595
|
+
console.log(chalk.gray(' /flow-docs-sync - Update documentation when code changes\n'));
|
|
628
596
|
}
|
|
629
597
|
else {
|
|
630
598
|
if (aiTools.includes('claude')) {
|
|
631
|
-
console.log(
|
|
632
|
-
console.log(
|
|
633
|
-
console.log(
|
|
599
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
600
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
601
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
634
602
|
}
|
|
635
603
|
else if (aiTools.includes('cursor')) {
|
|
636
|
-
console.log(
|
|
637
|
-
console.log(
|
|
638
|
-
console.log(
|
|
604
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
605
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
606
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
639
607
|
}
|
|
640
608
|
else {
|
|
641
|
-
console.log(
|
|
642
|
-
console.log(
|
|
643
|
-
console.log(
|
|
609
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
610
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
611
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
644
612
|
}
|
|
645
|
-
console.log(
|
|
646
|
-
console.log(
|
|
647
|
-
console.log(
|
|
613
|
+
console.log(chalk.white('Available slash commands:'));
|
|
614
|
+
console.log(chalk.gray(' /flow-bootstrap - Full 7-phase documentation generation'));
|
|
615
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-0-context - Context Discovery (existing projects)'));
|
|
648
616
|
if (selectedProjectType === 'backend') {
|
|
649
|
-
console.log(
|
|
650
|
-
console.log(
|
|
651
|
-
console.log(
|
|
652
|
-
console.log(
|
|
653
|
-
console.log(
|
|
654
|
-
console.log(
|
|
655
|
-
console.log(
|
|
617
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-business - Discovery & Business'));
|
|
618
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-data - Data Architecture'));
|
|
619
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-architecture - System Architecture'));
|
|
620
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-security - Security & Auth'));
|
|
621
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
622
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing'));
|
|
623
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-operations - Operations + Tools'));
|
|
656
624
|
}
|
|
657
625
|
else {
|
|
658
|
-
console.log(
|
|
659
|
-
console.log(
|
|
660
|
-
console.log(
|
|
661
|
-
console.log(
|
|
662
|
-
console.log(
|
|
663
|
-
console.log(
|
|
664
|
-
console.log(
|
|
626
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-discovery - Discovery & UX'));
|
|
627
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-components - Components & Framework'));
|
|
628
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-state - State Management'));
|
|
629
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-styling - Styling & Design'));
|
|
630
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
631
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing'));
|
|
632
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-deployment - Deployment'));
|
|
665
633
|
}
|
|
666
|
-
console.log(
|
|
634
|
+
console.log(chalk.gray(' /flow-docs-sync - Update documentation when code changes\n'));
|
|
667
635
|
}
|
|
668
636
|
if (flags?.dryRun) {
|
|
669
|
-
console.log(
|
|
637
|
+
console.log(chalk.yellow('⚠️ Dry-run: no files were written. Run again without --dry-run to apply changes.\n'));
|
|
670
638
|
}
|
|
671
|
-
console.log(
|
|
639
|
+
console.log(chalk.yellow('💡 Tip: You can run individual phases if you want to work step-by-step\n'));
|
|
672
640
|
}
|
|
673
641
|
catch (error) {
|
|
674
|
-
console.error(
|
|
642
|
+
console.error(chalk.red('\n❌ Initialization failed:'), fsErrorMessage(error));
|
|
675
643
|
process.exit(EXIT.FS_ERROR);
|
|
676
644
|
}
|
|
677
645
|
}
|
|
@@ -679,7 +647,7 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
679
647
|
program
|
|
680
648
|
.name('ai-flow')
|
|
681
649
|
.description('AI-powered development workflow from idea to production. Generate specs, plan features, and build with AI assistance.')
|
|
682
|
-
.version('1.
|
|
650
|
+
.version('1.1.2');
|
|
683
651
|
program
|
|
684
652
|
.command('init')
|
|
685
653
|
.description('Initialize AI Flow in current directory')
|
|
@@ -704,7 +672,7 @@ program
|
|
|
704
672
|
.action(async () => {
|
|
705
673
|
const isInitialized = await checkIfInitialized(process.cwd());
|
|
706
674
|
if (isInitialized) {
|
|
707
|
-
console.log(
|
|
675
|
+
console.log(chalk.green('✅ Project is initialized with AI Flow'));
|
|
708
676
|
const configPath = path.join(process.cwd(), '.ai-flow', 'core', 'config.json');
|
|
709
677
|
const config = await fs.readJSON(configPath);
|
|
710
678
|
// Detect project type (support both old and new config format)
|
|
@@ -725,65 +693,65 @@ program
|
|
|
725
693
|
: projectType === 'mobile'
|
|
726
694
|
? '📱 Mobile'
|
|
727
695
|
: '🔧 Backend';
|
|
728
|
-
console.log(
|
|
729
|
-
console.log(
|
|
730
|
-
console.log(
|
|
731
|
-
console.log(
|
|
732
|
-
console.log(
|
|
733
|
-
console.log(
|
|
696
|
+
console.log(chalk.white('\nConfiguration:'));
|
|
697
|
+
console.log(chalk.gray(` Version: ${config.version}`));
|
|
698
|
+
console.log(chalk.gray(` Project Type: ${projectTypeDisplay}`));
|
|
699
|
+
console.log(chalk.gray(` AI Tools: ${config.aiTools.join(', ')}`));
|
|
700
|
+
console.log(chalk.gray(` Created: ${new Date(config.createdAt).toLocaleString()}`));
|
|
701
|
+
console.log(chalk.gray(` Working Dir: ${process.cwd()}`));
|
|
734
702
|
// Show correct prompts path based on project type
|
|
735
703
|
if (projectType === 'fullstack') {
|
|
736
704
|
const backendPromptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', 'backend', 'bootstrap.md');
|
|
737
705
|
const frontendPromptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', 'frontend', 'bootstrap.md');
|
|
738
|
-
console.log(
|
|
739
|
-
console.log(
|
|
706
|
+
console.log(chalk.gray(` Backend Prompts: ${backendPromptsPath}`));
|
|
707
|
+
console.log(chalk.gray(` Frontend Prompts: ${frontendPromptsPath}`));
|
|
740
708
|
}
|
|
741
709
|
else {
|
|
742
710
|
const promptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', projectType, 'bootstrap.md');
|
|
743
|
-
console.log(
|
|
711
|
+
console.log(chalk.gray(` Prompts: ${promptsPath}`));
|
|
744
712
|
}
|
|
745
|
-
console.log(
|
|
713
|
+
console.log(chalk.white('\nNext steps:'));
|
|
746
714
|
if (projectType === 'fullstack') {
|
|
747
715
|
if (config.aiTools.includes('claude')) {
|
|
748
|
-
console.log(
|
|
749
|
-
console.log(
|
|
750
|
-
console.log(
|
|
716
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
717
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
718
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
751
719
|
}
|
|
752
720
|
else if (config.aiTools.includes('cursor')) {
|
|
753
|
-
console.log(
|
|
754
|
-
console.log(
|
|
755
|
-
console.log(
|
|
721
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
722
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
723
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
756
724
|
}
|
|
757
725
|
else {
|
|
758
726
|
const toolsText = config.aiTools.length === 1
|
|
759
727
|
? config.aiTools[0]
|
|
760
728
|
: `${config.aiTools.slice(0, -1).join(', ')} and ${config.aiTools[config.aiTools.length - 1]}`;
|
|
761
|
-
console.log(
|
|
762
|
-
console.log(
|
|
763
|
-
console.log(
|
|
729
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
730
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
731
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
764
732
|
}
|
|
765
733
|
}
|
|
766
734
|
else {
|
|
767
735
|
if (config.aiTools.includes('claude')) {
|
|
768
|
-
console.log(
|
|
769
|
-
console.log(
|
|
736
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
737
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
770
738
|
}
|
|
771
739
|
else if (config.aiTools.includes('cursor')) {
|
|
772
|
-
console.log(
|
|
773
|
-
console.log(
|
|
740
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
741
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
774
742
|
}
|
|
775
743
|
else {
|
|
776
744
|
const toolsText = config.aiTools.length === 1
|
|
777
745
|
? config.aiTools[0]
|
|
778
746
|
: `${config.aiTools.slice(0, -1).join(', ')} and ${config.aiTools[config.aiTools.length - 1]}`;
|
|
779
|
-
console.log(
|
|
780
|
-
console.log(
|
|
747
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
748
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
781
749
|
}
|
|
782
750
|
}
|
|
783
751
|
}
|
|
784
752
|
else {
|
|
785
|
-
console.log(
|
|
786
|
-
console.log(
|
|
753
|
+
console.log(chalk.yellow('⚠️ Project is not initialized'));
|
|
754
|
+
console.log(chalk.white('Run: ai-flow init .'));
|
|
787
755
|
}
|
|
788
756
|
});
|
|
789
757
|
program.parse();
|