ai-flow-dev 1.0.3 → 1.1.1
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 +201 -232
- 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/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,55 +85,55 @@ 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
138
|
type: 'list',
|
|
170
139
|
name: 'selectedTool',
|
|
@@ -185,8 +154,8 @@ async function selectProjectType(providedType) {
|
|
|
185
154
|
if (providedType) {
|
|
186
155
|
const valid = ['backend', 'frontend', 'fullstack', 'mobile'];
|
|
187
156
|
if (!valid.includes(providedType)) {
|
|
188
|
-
console.error(
|
|
189
|
-
console.log(
|
|
157
|
+
console.error(chalk.red(`❌ Invalid project type: ${providedType}`));
|
|
158
|
+
console.log(chalk.yellow('Available options: backend, frontend, fullstack, mobile'));
|
|
190
159
|
process.exit(EXIT.INVALID_ARGS);
|
|
191
160
|
}
|
|
192
161
|
return providedType;
|
|
@@ -197,7 +166,7 @@ async function selectProjectType(providedType) {
|
|
|
197
166
|
return 'backend';
|
|
198
167
|
}
|
|
199
168
|
// v1.4.0: Interactive selection for backend/frontend/fullstack/mobile
|
|
200
|
-
const answer = await
|
|
169
|
+
const answer = await inquirer.prompt([
|
|
201
170
|
{
|
|
202
171
|
type: 'list',
|
|
203
172
|
name: 'projectType',
|
|
@@ -217,7 +186,7 @@ async function checkIfInitialized(targetPath) {
|
|
|
217
186
|
return await fs.pathExists(bootstrapPath);
|
|
218
187
|
}
|
|
219
188
|
async function createBootstrapStructure(targetPath, aiTools, projectType = 'backend', dryRun, verbose) {
|
|
220
|
-
const spinner = (
|
|
189
|
+
const spinner = ora('Creating .ai-flow structure...').start();
|
|
221
190
|
try {
|
|
222
191
|
const bootstrapPath = path.join(targetPath, '.ai-flow');
|
|
223
192
|
// Create core directories
|
|
@@ -225,7 +194,7 @@ async function createBootstrapStructure(targetPath, aiTools, projectType = 'back
|
|
|
225
194
|
spinner.succeed('Created .ai-flow structure (dry-run)');
|
|
226
195
|
return;
|
|
227
196
|
}
|
|
228
|
-
await
|
|
197
|
+
await assertDirWritable(targetPath);
|
|
229
198
|
await fs.ensureDir(path.join(bootstrapPath, 'core'));
|
|
230
199
|
await fs.ensureDir(path.join(bootstrapPath, 'prompts'));
|
|
231
200
|
await fs.ensureDir(path.join(bootstrapPath, 'templates', 'docs'));
|
|
@@ -251,14 +220,14 @@ async function createBootstrapStructure(targetPath, aiTools, projectType = 'back
|
|
|
251
220
|
}
|
|
252
221
|
}
|
|
253
222
|
async function renderTemplates(targetPath, projectData, projectType = 'backend', aiTools = [], dryRun, verbose) {
|
|
254
|
-
const spinner = (
|
|
223
|
+
const spinner = ora('Generating documentation from templates...').start();
|
|
255
224
|
try {
|
|
256
225
|
const templatesTarget = path.join(targetPath, '.ai-flow', 'templates');
|
|
257
226
|
if (dryRun) {
|
|
258
227
|
spinner.succeed('Documentation generated from templates (dry-run)');
|
|
259
228
|
return;
|
|
260
229
|
}
|
|
261
|
-
await
|
|
230
|
+
await assertDirWritable(templatesTarget);
|
|
262
231
|
await fs.ensureDir(templatesTarget);
|
|
263
232
|
// Find all .template.md and .template files in a directory and subfolders
|
|
264
233
|
const walk = async (dir) => {
|
|
@@ -350,7 +319,7 @@ async function renderTemplates(targetPath, projectData, projectType = 'backend',
|
|
|
350
319
|
await fs.ensureDir(path.dirname(destPath));
|
|
351
320
|
const templateContent = await fs.readFile(templateFile, 'utf8');
|
|
352
321
|
// Render with EJS, leaving {{PLACEHOLDER}} for everything except name/description
|
|
353
|
-
const rendered =
|
|
322
|
+
const rendered = ejs.render(templateContent, {
|
|
354
323
|
PROJECT_NAME: projectData.name,
|
|
355
324
|
PROJECT_DESCRIPTION: projectData.description,
|
|
356
325
|
PROJECT_TYPE: projectType,
|
|
@@ -368,7 +337,7 @@ async function renderTemplates(targetPath, projectData, projectType = 'backend',
|
|
|
368
337
|
}
|
|
369
338
|
}
|
|
370
339
|
async function copyPrompts(targetPath, dryRun, verbose) {
|
|
371
|
-
const spinner = (
|
|
340
|
+
const spinner = ora('Copying master prompts...').start();
|
|
372
341
|
try {
|
|
373
342
|
const promptsSource = path.join(ROOT_DIR, 'prompts');
|
|
374
343
|
const promptsTarget = path.join(targetPath, '.ai-flow', 'prompts');
|
|
@@ -376,7 +345,7 @@ async function copyPrompts(targetPath, dryRun, verbose) {
|
|
|
376
345
|
spinner.succeed('Master prompts copied (dry-run)');
|
|
377
346
|
return;
|
|
378
347
|
}
|
|
379
|
-
await
|
|
348
|
+
await assertDirWritable(promptsTarget);
|
|
380
349
|
await fs.copy(promptsSource, promptsTarget);
|
|
381
350
|
logVerbose(`Copied prompts to ${promptsTarget}`, verbose);
|
|
382
351
|
spinner.succeed('Master prompts copied');
|
|
@@ -387,7 +356,7 @@ async function copyPrompts(targetPath, dryRun, verbose) {
|
|
|
387
356
|
}
|
|
388
357
|
}
|
|
389
358
|
async function setupSlashCommands(targetPath, aiTools, projectType = 'backend', dryRun, verbose) {
|
|
390
|
-
const spinner = (
|
|
359
|
+
const spinner = ora('Setting up slash commands...').start();
|
|
391
360
|
try {
|
|
392
361
|
// Determine which prompt directories to copy from
|
|
393
362
|
const promptSources = [];
|
|
@@ -415,7 +384,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
415
384
|
// Copilot: prompts in .github/prompts with .prompt.md suffix
|
|
416
385
|
const promptsTarget = path.join(targetPath, '.github', 'prompts');
|
|
417
386
|
if (!dryRun) {
|
|
418
|
-
await
|
|
387
|
+
await assertDirWritable(promptsTarget);
|
|
419
388
|
await fs.ensureDir(promptsTarget);
|
|
420
389
|
}
|
|
421
390
|
for (const file of files) {
|
|
@@ -433,7 +402,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
433
402
|
else if (tool === 'claude') {
|
|
434
403
|
const commandsTarget = path.join(targetPath, '.claude', 'commands');
|
|
435
404
|
if (!dryRun) {
|
|
436
|
-
await
|
|
405
|
+
await assertDirWritable(commandsTarget);
|
|
437
406
|
await fs.ensureDir(commandsTarget);
|
|
438
407
|
}
|
|
439
408
|
for (const file of files) {
|
|
@@ -448,7 +417,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
448
417
|
else if (tool === 'cursor') {
|
|
449
418
|
const commandsTarget = path.join(targetPath, '.cursor', 'commands');
|
|
450
419
|
if (!dryRun) {
|
|
451
|
-
await
|
|
420
|
+
await assertDirWritable(commandsTarget);
|
|
452
421
|
await fs.ensureDir(commandsTarget);
|
|
453
422
|
}
|
|
454
423
|
for (const file of files) {
|
|
@@ -463,7 +432,7 @@ async function setupSlashCommands(targetPath, aiTools, projectType = 'backend',
|
|
|
463
432
|
else if (tool === 'gemini') {
|
|
464
433
|
const commandsTarget = path.join(targetPath, '.gemini', 'commands');
|
|
465
434
|
if (!dryRun) {
|
|
466
|
-
await
|
|
435
|
+
await assertDirWritable(commandsTarget);
|
|
467
436
|
await fs.ensureDir(commandsTarget);
|
|
468
437
|
}
|
|
469
438
|
for (const file of files) {
|
|
@@ -489,8 +458,8 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
489
458
|
// Check if already initialized
|
|
490
459
|
const isInitialized = await checkIfInitialized(targetPath);
|
|
491
460
|
if (isInitialized) {
|
|
492
|
-
console.log(
|
|
493
|
-
const { reinitialize } = await
|
|
461
|
+
console.log(chalk.yellow('\n⚠️ Project already initialized with AI Flow'));
|
|
462
|
+
const { reinitialize } = await inquirer.prompt([
|
|
494
463
|
{
|
|
495
464
|
type: 'confirm',
|
|
496
465
|
name: 'reinitialize',
|
|
@@ -499,7 +468,7 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
499
468
|
},
|
|
500
469
|
]);
|
|
501
470
|
if (!reinitialize) {
|
|
502
|
-
console.log(
|
|
471
|
+
console.log(chalk.blue('Initialization cancelled'));
|
|
503
472
|
return;
|
|
504
473
|
}
|
|
505
474
|
}
|
|
@@ -515,17 +484,17 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
515
484
|
.join(' ');
|
|
516
485
|
// Request minimal project data only if not provided
|
|
517
486
|
if (projectName && !isValidName(projectName)) {
|
|
518
|
-
console.error(
|
|
487
|
+
console.error(chalk.red('Invalid project name'));
|
|
519
488
|
process.exit(EXIT.INVALID_ARGS);
|
|
520
489
|
}
|
|
521
490
|
if (projectDescription && !isValidDescription(projectDescription)) {
|
|
522
|
-
console.error(
|
|
491
|
+
console.error(chalk.red('Invalid project description'));
|
|
523
492
|
process.exit(EXIT.INVALID_ARGS);
|
|
524
493
|
}
|
|
525
494
|
let finalProjectName = projectName;
|
|
526
|
-
let finalProjectDescription = projectDescription || 'TBD - Run /flow-
|
|
495
|
+
let finalProjectDescription = projectDescription || 'TBD - Run /flow-bootstrap to define';
|
|
527
496
|
if (!finalProjectName) {
|
|
528
|
-
const answers = await
|
|
497
|
+
const answers = await inquirer.prompt([
|
|
529
498
|
{
|
|
530
499
|
type: 'input',
|
|
531
500
|
name: 'projectName',
|
|
@@ -537,141 +506,141 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
537
506
|
]);
|
|
538
507
|
finalProjectName = answers.projectName;
|
|
539
508
|
}
|
|
540
|
-
console.log(
|
|
509
|
+
console.log(chalk.cyan('\n📦 Initializing AI Flow...\n'));
|
|
541
510
|
// Create structure
|
|
542
511
|
await createBootstrapStructure(targetPath, aiTools, selectedProjectType, flags?.dryRun, flags?.verbose);
|
|
543
512
|
await renderTemplates(targetPath, { name: finalProjectName, description: finalProjectDescription }, selectedProjectType, aiTools, flags?.dryRun, flags?.verbose);
|
|
544
513
|
await copyPrompts(targetPath, flags?.dryRun, flags?.verbose);
|
|
545
514
|
await setupSlashCommands(targetPath, aiTools, selectedProjectType, flags?.dryRun, flags?.verbose);
|
|
546
515
|
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(
|
|
516
|
+
console.log(chalk.green('\n✅ AI Flow initialized successfully!'));
|
|
517
|
+
console.log(chalk.white('\nSummary:'));
|
|
518
|
+
console.log(chalk.gray(` Project: ${finalProjectName}`));
|
|
519
|
+
console.log(chalk.gray(` Version: ${PKG_VERSION}`));
|
|
520
|
+
console.log(chalk.gray(` Directory: ${targetPath}`));
|
|
521
|
+
console.log(chalk.gray(` Tools: ${aiTools.join(', ')}`));
|
|
522
|
+
console.log(chalk.gray(` Mode: ${modeText}`));
|
|
523
|
+
console.log(chalk.white('\nNext steps:\n'));
|
|
555
524
|
const toolsText = aiTools.length === 1
|
|
556
525
|
? aiTools[0]
|
|
557
526
|
: `${aiTools.slice(0, -1).join(', ')} and ${aiTools[aiTools.length - 1]}`;
|
|
558
527
|
if (selectedProjectType === 'fullstack') {
|
|
559
528
|
if (aiTools.includes('claude')) {
|
|
560
|
-
console.log(
|
|
561
|
-
console.log(
|
|
562
|
-
console.log(
|
|
563
|
-
console.log(
|
|
529
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
530
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
531
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
532
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
564
533
|
}
|
|
565
534
|
else if (aiTools.includes('cursor')) {
|
|
566
|
-
console.log(
|
|
567
|
-
console.log(
|
|
568
|
-
console.log(
|
|
569
|
-
console.log(
|
|
535
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
536
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
537
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
538
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
570
539
|
}
|
|
571
540
|
else {
|
|
572
|
-
console.log(
|
|
573
|
-
console.log(
|
|
574
|
-
console.log(
|
|
575
|
-
console.log(
|
|
541
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
542
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
543
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
544
|
+
console.log(chalk.gray(' Each will guide you through 7 phases\n'));
|
|
576
545
|
}
|
|
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(
|
|
546
|
+
console.log(chalk.white('Available slash commands:'));
|
|
547
|
+
console.log(chalk.gray(' Backend commands:'));
|
|
548
|
+
console.log(chalk.gray(' /backend-flow-bootstrap - Backend 7-phase documentation generation'));
|
|
549
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-0-context - Backend context discovery'));
|
|
550
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-1-business - Backend discovery & business'));
|
|
551
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-2-data - Backend data architecture'));
|
|
552
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-3-architecture - Backend system architecture'));
|
|
553
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-4-security - Backend security & auth'));
|
|
554
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-5-standards - Backend code standards'));
|
|
555
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-6-testing - Backend testing'));
|
|
556
|
+
console.log(chalk.gray(' /backend-flow-bootstrap-phase-7-operations - Backend operations + tools'));
|
|
557
|
+
console.log(chalk.gray(' /backend-flow-docs-sync - Update backend documentation\n'));
|
|
558
|
+
console.log(chalk.gray(' Frontend commands:'));
|
|
559
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap - Frontend 7-phase documentation generation'));
|
|
560
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-0-context - Frontend context discovery'));
|
|
561
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-1-discovery - Frontend discovery & UX'));
|
|
562
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-2-components - Frontend components & framework'));
|
|
563
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-3-state - Frontend state management'));
|
|
564
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-4-styling - Frontend styling & design'));
|
|
565
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-5-standards - Frontend code standards'));
|
|
566
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-6-testing - Frontend testing'));
|
|
567
|
+
console.log(chalk.gray(' /frontend-flow-bootstrap-phase-7-deployment - Frontend deployment'));
|
|
568
|
+
console.log(chalk.gray(' /frontend-flow-docs-sync - Update frontend documentation\n'));
|
|
600
569
|
}
|
|
601
570
|
else if (selectedProjectType === 'mobile') {
|
|
602
571
|
if (aiTools.includes('claude')) {
|
|
603
|
-
console.log(
|
|
604
|
-
console.log(
|
|
605
|
-
console.log(
|
|
572
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
573
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
574
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
606
575
|
}
|
|
607
576
|
else if (aiTools.includes('cursor')) {
|
|
608
|
-
console.log(
|
|
609
|
-
console.log(
|
|
610
|
-
console.log(
|
|
577
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
578
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
579
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
611
580
|
}
|
|
612
581
|
else {
|
|
613
|
-
console.log(
|
|
614
|
-
console.log(
|
|
615
|
-
console.log(
|
|
582
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
583
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
584
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
616
585
|
}
|
|
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(
|
|
586
|
+
console.log(chalk.white('Available slash commands:'));
|
|
587
|
+
console.log(chalk.gray(' /flow-bootstrap - Full 7-phase documentation generation'));
|
|
588
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-0-context - Context Discovery (existing projects)'));
|
|
589
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-platform - Platform & Framework Selection'));
|
|
590
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-navigation - Navigation & Architecture'));
|
|
591
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-state - State & Data Management'));
|
|
592
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-permissions - Permissions & Native Features'));
|
|
593
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
594
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing Strategy'));
|
|
595
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-deployment - Store Deployment'));
|
|
596
|
+
console.log(chalk.gray(' /flow-docs-sync - Update documentation when code changes\n'));
|
|
628
597
|
}
|
|
629
598
|
else {
|
|
630
599
|
if (aiTools.includes('claude')) {
|
|
631
|
-
console.log(
|
|
632
|
-
console.log(
|
|
633
|
-
console.log(
|
|
600
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
601
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
602
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
634
603
|
}
|
|
635
604
|
else if (aiTools.includes('cursor')) {
|
|
636
|
-
console.log(
|
|
637
|
-
console.log(
|
|
638
|
-
console.log(
|
|
605
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
606
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
607
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
639
608
|
}
|
|
640
609
|
else {
|
|
641
|
-
console.log(
|
|
642
|
-
console.log(
|
|
643
|
-
console.log(
|
|
610
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
611
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
612
|
+
console.log(chalk.gray(' This will start the 7-phase interactive setup\n'));
|
|
644
613
|
}
|
|
645
|
-
console.log(
|
|
646
|
-
console.log(
|
|
647
|
-
console.log(
|
|
614
|
+
console.log(chalk.white('Available slash commands:'));
|
|
615
|
+
console.log(chalk.gray(' /flow-bootstrap - Full 7-phase documentation generation'));
|
|
616
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-0-context - Context Discovery (existing projects)'));
|
|
648
617
|
if (selectedProjectType === 'backend') {
|
|
649
|
-
console.log(
|
|
650
|
-
console.log(
|
|
651
|
-
console.log(
|
|
652
|
-
console.log(
|
|
653
|
-
console.log(
|
|
654
|
-
console.log(
|
|
655
|
-
console.log(
|
|
618
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-business - Discovery & Business'));
|
|
619
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-data - Data Architecture'));
|
|
620
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-architecture - System Architecture'));
|
|
621
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-security - Security & Auth'));
|
|
622
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
623
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing'));
|
|
624
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-operations - Operations + Tools'));
|
|
656
625
|
}
|
|
657
626
|
else {
|
|
658
|
-
console.log(
|
|
659
|
-
console.log(
|
|
660
|
-
console.log(
|
|
661
|
-
console.log(
|
|
662
|
-
console.log(
|
|
663
|
-
console.log(
|
|
664
|
-
console.log(
|
|
627
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-1-discovery - Discovery & UX'));
|
|
628
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-2-components - Components & Framework'));
|
|
629
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-3-state - State Management'));
|
|
630
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-4-styling - Styling & Design'));
|
|
631
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-5-standards - Code Standards'));
|
|
632
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-6-testing - Testing'));
|
|
633
|
+
console.log(chalk.gray(' /flow-bootstrap-phase-7-deployment - Deployment'));
|
|
665
634
|
}
|
|
666
|
-
console.log(
|
|
635
|
+
console.log(chalk.gray(' /flow-docs-sync - Update documentation when code changes\n'));
|
|
667
636
|
}
|
|
668
637
|
if (flags?.dryRun) {
|
|
669
|
-
console.log(
|
|
638
|
+
console.log(chalk.yellow('⚠️ Dry-run: no files were written. Run again without --dry-run to apply changes.\n'));
|
|
670
639
|
}
|
|
671
|
-
console.log(
|
|
640
|
+
console.log(chalk.yellow('💡 Tip: You can run individual phases if you want to work step-by-step\n'));
|
|
672
641
|
}
|
|
673
642
|
catch (error) {
|
|
674
|
-
console.error(
|
|
643
|
+
console.error(chalk.red('\n❌ Initialization failed:'), fsErrorMessage(error));
|
|
675
644
|
process.exit(EXIT.FS_ERROR);
|
|
676
645
|
}
|
|
677
646
|
}
|
|
@@ -679,7 +648,7 @@ async function initializeProject(targetPath, aiTool, projectType, projectName, p
|
|
|
679
648
|
program
|
|
680
649
|
.name('ai-flow')
|
|
681
650
|
.description('AI-powered development workflow from idea to production. Generate specs, plan features, and build with AI assistance.')
|
|
682
|
-
.version('1.
|
|
651
|
+
.version('1.1.1');
|
|
683
652
|
program
|
|
684
653
|
.command('init')
|
|
685
654
|
.description('Initialize AI Flow in current directory')
|
|
@@ -704,7 +673,7 @@ program
|
|
|
704
673
|
.action(async () => {
|
|
705
674
|
const isInitialized = await checkIfInitialized(process.cwd());
|
|
706
675
|
if (isInitialized) {
|
|
707
|
-
console.log(
|
|
676
|
+
console.log(chalk.green('✅ Project is initialized with AI Flow'));
|
|
708
677
|
const configPath = path.join(process.cwd(), '.ai-flow', 'core', 'config.json');
|
|
709
678
|
const config = await fs.readJSON(configPath);
|
|
710
679
|
// Detect project type (support both old and new config format)
|
|
@@ -725,65 +694,65 @@ program
|
|
|
725
694
|
: projectType === 'mobile'
|
|
726
695
|
? '📱 Mobile'
|
|
727
696
|
: '🔧 Backend';
|
|
728
|
-
console.log(
|
|
729
|
-
console.log(
|
|
730
|
-
console.log(
|
|
731
|
-
console.log(
|
|
732
|
-
console.log(
|
|
733
|
-
console.log(
|
|
697
|
+
console.log(chalk.white('\nConfiguration:'));
|
|
698
|
+
console.log(chalk.gray(` Version: ${config.version}`));
|
|
699
|
+
console.log(chalk.gray(` Project Type: ${projectTypeDisplay}`));
|
|
700
|
+
console.log(chalk.gray(` AI Tools: ${config.aiTools.join(', ')}`));
|
|
701
|
+
console.log(chalk.gray(` Created: ${new Date(config.createdAt).toLocaleString()}`));
|
|
702
|
+
console.log(chalk.gray(` Working Dir: ${process.cwd()}`));
|
|
734
703
|
// Show correct prompts path based on project type
|
|
735
704
|
if (projectType === 'fullstack') {
|
|
736
705
|
const backendPromptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', 'backend', 'bootstrap.md');
|
|
737
706
|
const frontendPromptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', 'frontend', 'bootstrap.md');
|
|
738
|
-
console.log(
|
|
739
|
-
console.log(
|
|
707
|
+
console.log(chalk.gray(` Backend Prompts: ${backendPromptsPath}`));
|
|
708
|
+
console.log(chalk.gray(` Frontend Prompts: ${frontendPromptsPath}`));
|
|
740
709
|
}
|
|
741
710
|
else {
|
|
742
711
|
const promptsPath = path.join(process.cwd(), '.ai-flow', 'prompts', projectType, 'bootstrap.md');
|
|
743
|
-
console.log(
|
|
712
|
+
console.log(chalk.gray(` Prompts: ${promptsPath}`));
|
|
744
713
|
}
|
|
745
|
-
console.log(
|
|
714
|
+
console.log(chalk.white('\nNext steps:'));
|
|
746
715
|
if (projectType === 'fullstack') {
|
|
747
716
|
if (config.aiTools.includes('claude')) {
|
|
748
|
-
console.log(
|
|
749
|
-
console.log(
|
|
750
|
-
console.log(
|
|
717
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
718
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
719
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
751
720
|
}
|
|
752
721
|
else if (config.aiTools.includes('cursor')) {
|
|
753
|
-
console.log(
|
|
754
|
-
console.log(
|
|
755
|
-
console.log(
|
|
722
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
723
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
724
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
756
725
|
}
|
|
757
726
|
else {
|
|
758
727
|
const toolsText = config.aiTools.length === 1
|
|
759
728
|
? config.aiTools[0]
|
|
760
729
|
: `${config.aiTools.slice(0, -1).join(', ')} and ${config.aiTools[config.aiTools.length - 1]}`;
|
|
761
|
-
console.log(
|
|
762
|
-
console.log(
|
|
763
|
-
console.log(
|
|
730
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
731
|
+
console.log(chalk.cyan(' 2. Run: /backend-flow-bootstrap (for backend documentation)'));
|
|
732
|
+
console.log(chalk.cyan(' 3. Run: /frontend-flow-bootstrap (for frontend documentation)'));
|
|
764
733
|
}
|
|
765
734
|
}
|
|
766
735
|
else {
|
|
767
736
|
if (config.aiTools.includes('claude')) {
|
|
768
|
-
console.log(
|
|
769
|
-
console.log(
|
|
737
|
+
console.log(chalk.cyan(' 1. Open Claude Code'));
|
|
738
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
770
739
|
}
|
|
771
740
|
else if (config.aiTools.includes('cursor')) {
|
|
772
|
-
console.log(
|
|
773
|
-
console.log(
|
|
741
|
+
console.log(chalk.cyan(' 1. Open Cursor'));
|
|
742
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
774
743
|
}
|
|
775
744
|
else {
|
|
776
745
|
const toolsText = config.aiTools.length === 1
|
|
777
746
|
? config.aiTools[0]
|
|
778
747
|
: `${config.aiTools.slice(0, -1).join(', ')} and ${config.aiTools[config.aiTools.length - 1]}`;
|
|
779
|
-
console.log(
|
|
780
|
-
console.log(
|
|
748
|
+
console.log(chalk.cyan(` 1. Open your AI tool (${toolsText})`));
|
|
749
|
+
console.log(chalk.cyan(' 2. Run: /bootstrap'));
|
|
781
750
|
}
|
|
782
751
|
}
|
|
783
752
|
}
|
|
784
753
|
else {
|
|
785
|
-
console.log(
|
|
786
|
-
console.log(
|
|
754
|
+
console.log(chalk.yellow('⚠️ Project is not initialized'));
|
|
755
|
+
console.log(chalk.white('Run: ai-flow init .'));
|
|
787
756
|
}
|
|
788
757
|
});
|
|
789
758
|
program.parse();
|