@itz4blitz/agentful 0.1.0 → 0.1.5
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/.claude/agents/architect.md +283 -11
- package/.claude/agents/backend.md +282 -218
- package/.claude/agents/frontend.md +242 -319
- package/.claude/agents/orchestrator.md +27 -27
- package/.claude/agents/reviewer.md +1 -1
- package/.claude/agents/tester.md +375 -284
- package/.claude/commands/agentful-decide.md +104 -29
- package/.claude/commands/agentful-start.md +18 -16
- package/.claude/commands/agentful-status.md +28 -22
- package/.claude/commands/agentful-validate.md +42 -20
- package/.claude/commands/agentful.md +329 -0
- package/.claude/product/README.md +1 -1
- package/.claude/product/index.md +1 -1
- package/.claude/settings.json +4 -3
- package/.claude/skills/conversation/SKILL.md +1130 -0
- package/LICENSE +1 -1
- package/README.md +557 -222
- package/bin/cli.js +319 -36
- package/lib/agent-generator.js +685 -0
- package/lib/domain-detector.js +468 -0
- package/lib/domain-structure-generator.js +770 -0
- package/lib/index.js +40 -0
- package/lib/project-analyzer.js +701 -0
- package/lib/tech-stack-detector.js +1091 -0
- package/lib/template-engine.js +153 -0
- package/package.json +14 -5
- package/template/CLAUDE.md +62 -21
- package/template/PRODUCT.md +89 -1
package/bin/cli.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* agentful CLI
|
|
5
|
+
* An opinionated autonomous product development kit for Claude Code
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import fs from 'fs';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
+
import { analyzeProject, exportToArchitectureJson } from '../lib/project-analyzer.js';
|
|
12
|
+
import AgentGenerator from '../lib/agent-generator.js';
|
|
13
|
+
import DomainStructureGenerator from '../lib/domain-structure-generator.js';
|
|
11
14
|
|
|
12
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
16
|
const __dirname = path.dirname(__filename);
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
// Read version from centralized config
|
|
19
|
+
const VERSION = JSON.parse(fs.readFileSync(path.join(__dirname, '../version.json'), 'utf-8')).version;
|
|
16
20
|
const AGENTFUL_DIR = path.resolve(__dirname, '..');
|
|
17
21
|
const TEMPLATE_DIR = path.join(AGENTFUL_DIR, 'template');
|
|
18
22
|
|
|
@@ -35,13 +39,14 @@ function log(color, ...args) {
|
|
|
35
39
|
|
|
36
40
|
function showBanner() {
|
|
37
41
|
console.log('');
|
|
38
|
-
log(colors.cyan, '
|
|
39
|
-
log(colors.cyan, '
|
|
40
|
-
log(colors.cyan, '
|
|
41
|
-
log(colors.cyan, '
|
|
42
|
-
log(colors.cyan, '
|
|
42
|
+
log(colors.cyan, ' █████╗ ██████╗ ███████╗███╗ ██╗████████╗███████╗██╗ ██╗██╗ ');
|
|
43
|
+
log(colors.cyan, ' ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██╔════╝██║ ██║██║ ');
|
|
44
|
+
log(colors.cyan, ' ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ █████╗ ██║ ██║██║ ');
|
|
45
|
+
log(colors.cyan, ' ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██╔══╝ ██║ ██║██║ ');
|
|
46
|
+
log(colors.cyan, ' ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ██║ ╚██████╔╝███████╗');
|
|
47
|
+
log(colors.cyan, ' ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝');
|
|
43
48
|
console.log('');
|
|
44
|
-
log(colors.dim, ` v${VERSION}
|
|
49
|
+
log(colors.dim, ` v${VERSION} `);
|
|
45
50
|
console.log('');
|
|
46
51
|
}
|
|
47
52
|
|
|
@@ -51,19 +56,25 @@ function showHelp() {
|
|
|
51
56
|
console.log(` ${colors.bright}agentful${colors.reset} ${colors.green}<command>${colors.reset}`);
|
|
52
57
|
console.log('');
|
|
53
58
|
console.log('COMMANDS:');
|
|
54
|
-
console.log(` ${colors.green}init${colors.reset} Initialize
|
|
59
|
+
console.log(` ${colors.green}init${colors.reset} Initialize agentful in current directory`);
|
|
55
60
|
console.log(` ${colors.green}init --bare${colors.reset} Skip creating templates (just .claude/)`);
|
|
61
|
+
console.log(` ${colors.green}init --no-smart${colors.reset} Skip smart analysis (basic init only)`);
|
|
62
|
+
console.log(` ${colors.green}init --deep${colors.reset} Run deep analysis (slower, more thorough)`);
|
|
63
|
+
console.log(` ${colors.green}init --generate-agents${colors.reset} Auto-generate agents`);
|
|
64
|
+
console.log(` ${colors.green}init --generate-domains${colors.reset} Auto-generate domain structure`);
|
|
56
65
|
console.log(` ${colors.green}generate${colors.reset} Generate specialized agents from tech stack`);
|
|
57
66
|
console.log(` ${colors.green}status${colors.reset} Show current development progress`);
|
|
58
67
|
console.log(` ${colors.green}--help${colors.reset} Show this help message`);
|
|
59
68
|
console.log(` ${colors.green}--version${colors.reset} Show version`);
|
|
60
69
|
console.log('');
|
|
61
70
|
console.log('AFTER INIT:');
|
|
62
|
-
console.log(` 1.
|
|
63
|
-
console.log(`
|
|
64
|
-
console.log(`
|
|
65
|
-
console.log(`
|
|
66
|
-
console.log(`
|
|
71
|
+
console.log(` 1. ${colors.bright}agentful automatically detects the best structure:${colors.reset}`);
|
|
72
|
+
console.log(` ${colors.green}• Small projects:${colors.reset} Creates PRODUCT.md (simple, flat structure)`);
|
|
73
|
+
console.log(` ${colors.cyan}• Large/complex projects:${colors.reset} Creates .claude/product/ with domains`);
|
|
74
|
+
console.log(` ${colors.dim}(Detection based on: # of domains, frameworks, monorepo status)${colors.reset}`);
|
|
75
|
+
console.log(` 2. ${colors.bright}Edit your product specification${colors.reset}`);
|
|
76
|
+
console.log(` 3. Run ${colors.bright}claude${colors.reset} to start Claude Code`);
|
|
77
|
+
console.log(` 4. Type ${colors.bright}/agentful${colors.reset} for natural conversation or ${colors.bright}/agentful-start${colors.reset} for autonomous development`);
|
|
67
78
|
console.log('');
|
|
68
79
|
console.log('FOR 24/7 DEVELOPMENT:');
|
|
69
80
|
console.log(` ${colors.cyan}/ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"${colors.reset}`);
|
|
@@ -71,7 +82,7 @@ function showHelp() {
|
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
function showVersion() {
|
|
74
|
-
console.log(`
|
|
85
|
+
console.log(`agentful v${VERSION}`);
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
function copyDir(src, dest) {
|
|
@@ -98,7 +109,7 @@ function checkGitignore() {
|
|
|
98
109
|
content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
99
110
|
}
|
|
100
111
|
|
|
101
|
-
const agentfulIgnore = '#
|
|
112
|
+
const agentfulIgnore = '# agentful runtime state\n.agentful/\n';
|
|
102
113
|
|
|
103
114
|
if (!content.includes('.agentful/')) {
|
|
104
115
|
fs.appendFileSync(gitignorePath, agentfulIgnore);
|
|
@@ -106,13 +117,20 @@ function checkGitignore() {
|
|
|
106
117
|
}
|
|
107
118
|
}
|
|
108
119
|
|
|
109
|
-
async function
|
|
120
|
+
async function initagentful(options = {}) {
|
|
110
121
|
showBanner();
|
|
111
122
|
|
|
112
123
|
const targetDir = process.cwd();
|
|
113
124
|
const claudeDir = path.join(targetDir, '.claude');
|
|
114
125
|
const agentfulDir = path.join(targetDir, '.agentful');
|
|
115
126
|
|
|
127
|
+
// Parse options
|
|
128
|
+
const bare = options.bare || false;
|
|
129
|
+
const smart = options.smart !== false; // Default: true
|
|
130
|
+
const deep = options.deep || false;
|
|
131
|
+
const autoGenerateAgents = options.generateAgents || false;
|
|
132
|
+
const autoGenerateDomains = options.generateDomains || false;
|
|
133
|
+
|
|
116
134
|
// Check if already initialized
|
|
117
135
|
if (fs.existsSync(claudeDir)) {
|
|
118
136
|
log(colors.yellow, '⚠️ .claude/ directory already exists!');
|
|
@@ -156,7 +174,7 @@ async function initAgentful(options = { bare: false }) {
|
|
|
156
174
|
path.join(agentfulDir, 'state.json'),
|
|
157
175
|
JSON.stringify(
|
|
158
176
|
{
|
|
159
|
-
version: '0.1.
|
|
177
|
+
version: '0.1.1',
|
|
160
178
|
current_task: null,
|
|
161
179
|
current_phase: 'idle',
|
|
162
180
|
iterations: 0,
|
|
@@ -208,11 +226,12 @@ async function initAgentful(options = { bare: false }) {
|
|
|
208
226
|
);
|
|
209
227
|
|
|
210
228
|
// Copy templates if not bare mode
|
|
211
|
-
if (!
|
|
229
|
+
if (!bare) {
|
|
212
230
|
log(colors.dim, 'Creating template files...');
|
|
213
231
|
|
|
214
232
|
const claudeMdPath = path.join(targetDir, 'CLAUDE.md');
|
|
215
233
|
const productMdPath = path.join(targetDir, 'PRODUCT.md');
|
|
234
|
+
const claudeProductDir = path.join(targetDir, '.claude/product');
|
|
216
235
|
|
|
217
236
|
if (!fs.existsSync(claudeMdPath)) {
|
|
218
237
|
fs.copyFileSync(
|
|
@@ -224,41 +243,297 @@ async function initAgentful(options = { bare: false }) {
|
|
|
224
243
|
log(colors.dim, ' ⊙ CLAUDE.md already exists, skipping');
|
|
225
244
|
}
|
|
226
245
|
|
|
227
|
-
if
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
)
|
|
232
|
-
|
|
246
|
+
// Determine if project should use hierarchical structure
|
|
247
|
+
const shouldUseHierarchical = analysis && (
|
|
248
|
+
analysis.domains.length >= 3 || // Multiple detected domains
|
|
249
|
+
(analysis.frameworks && analysis.frameworks.length >= 2) || // Multiple frameworks
|
|
250
|
+
(analysis.packageManager === 'workspace' || analysis.packageManager === 'monorepo') // Monorepo
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// Create appropriate product structure
|
|
254
|
+
const productExists = fs.existsSync(productMdPath) || fs.existsSync(claudeProductDir);
|
|
255
|
+
|
|
256
|
+
if (!productExists) {
|
|
257
|
+
if (shouldUseHierarchical) {
|
|
258
|
+
// Create hierarchical .claude/product/ structure
|
|
259
|
+
log(colors.dim, ' 📁 Using hierarchical product structure (detected complex project)');
|
|
260
|
+
fs.mkdirSync(claudeProductDir, { recursive: true });
|
|
261
|
+
fs.mkdirSync(path.join(claudeProductDir, 'domains'), { recursive: true });
|
|
262
|
+
|
|
263
|
+
// Create main index.md
|
|
264
|
+
const indexContent = `# Product Specification
|
|
265
|
+
|
|
266
|
+
## Overview
|
|
267
|
+
[Describe your product here]
|
|
268
|
+
|
|
269
|
+
## Tech Stack
|
|
270
|
+
${analysis && analysis.language ? `- Language: ${analysis.language}` : ''}
|
|
271
|
+
${analysis && analysis.frameworks && analysis.frameworks.length > 0 ? `- Frameworks: ${analysis.frameworks.join(', ')}` : ''}
|
|
272
|
+
${analysis && analysis.packageManager && analysis.packageManager !== 'unknown' ? `- Package Manager: ${analysis.packageManager}` : ''}
|
|
273
|
+
|
|
274
|
+
## Domains
|
|
275
|
+
${analysis && analysis.domains.length > 0 ? analysis.domains.map((d, i) => `${i + 1}. [${d}] - Define details in \`domains/${d.toLowerCase().replace(/\s+/g, '-')}/index.md\``).join('\n') : '- [Domain 1] - Define in domains/domain-name/index.md\n- [Domain 2] - Define in domains/domain-name/index.md'}
|
|
276
|
+
|
|
277
|
+
## Priority Legend
|
|
278
|
+
- **CRITICAL**: Must have for launch
|
|
279
|
+
- **HIGH**: Important for MVP
|
|
280
|
+
- **MEDIUM**: Nice to have
|
|
281
|
+
- **LOW**: Future consideration
|
|
282
|
+
`;
|
|
283
|
+
|
|
284
|
+
fs.writeFileSync(path.join(claudeProductDir, 'index.md'), indexContent);
|
|
285
|
+
|
|
286
|
+
// Create domain directories with index files for detected domains
|
|
287
|
+
if (analysis && analysis.domains.length > 0) {
|
|
288
|
+
analysis.domains.slice(0, 8).forEach(domain => {
|
|
289
|
+
const domainDir = path.join(claudeProductDir, 'domains', domain.toLowerCase().replace(/\s+/g, '-'));
|
|
290
|
+
fs.mkdirSync(domainDir, { recursive: true });
|
|
291
|
+
|
|
292
|
+
const domainIndexContent = `# ${domain} Domain
|
|
293
|
+
|
|
294
|
+
## Overview
|
|
295
|
+
[Describe the ${domain} domain's purpose and scope]
|
|
296
|
+
|
|
297
|
+
## Features
|
|
298
|
+
1. [Feature 1] (CRITICAL)
|
|
299
|
+
- [Acceptance criteria]
|
|
300
|
+
- [Dependencies]
|
|
301
|
+
|
|
302
|
+
2. [Feature 2] (HIGH)
|
|
303
|
+
- [Acceptance criteria]
|
|
304
|
+
|
|
305
|
+
## Technical Notes
|
|
306
|
+
- [Any technical considerations specific to this domain]
|
|
307
|
+
`;
|
|
308
|
+
fs.writeFileSync(path.join(domainDir, 'index.md'), domainIndexContent);
|
|
309
|
+
});
|
|
310
|
+
} else {
|
|
311
|
+
// Create example domain structure
|
|
312
|
+
const exampleDomainDir = path.join(claudeProductDir, 'domains', 'example-domain');
|
|
313
|
+
fs.mkdirSync(exampleDomainDir, { recursive: true });
|
|
314
|
+
fs.writeFileSync(
|
|
315
|
+
path.join(exampleDomainDir, 'index.md'),
|
|
316
|
+
'# Example Domain\n\n## Overview\n[Describe this domain]\n\n## Features\n1. Example Feature (HIGH)\n'
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
log(colors.green, ' ✓ Created .claude/product/ with domain structure');
|
|
321
|
+
log(colors.dim, ` → Organized by ${analysis.domains.length > 0 ? analysis.domains.length : 'example'} domain(s)`);
|
|
322
|
+
} else {
|
|
323
|
+
// Create flat PRODUCT.md structure
|
|
324
|
+
log(colors.dim, ' 📄 Using flat product structure (simple project)');
|
|
325
|
+
fs.copyFileSync(
|
|
326
|
+
path.join(TEMPLATE_DIR, 'PRODUCT.md'),
|
|
327
|
+
productMdPath
|
|
328
|
+
);
|
|
329
|
+
log(colors.green, ' ✓ Created PRODUCT.md');
|
|
330
|
+
}
|
|
233
331
|
} else {
|
|
234
|
-
log(colors.dim, ' ⊙
|
|
332
|
+
log(colors.dim, ' ⊙ Product spec already exists, skipping');
|
|
235
333
|
}
|
|
236
334
|
}
|
|
237
335
|
|
|
238
336
|
// Update .gitignore
|
|
239
337
|
checkGitignore();
|
|
240
338
|
|
|
339
|
+
// Perform smart project analysis (unless explicitly disabled)
|
|
340
|
+
let analysis = null;
|
|
341
|
+
if (smart) {
|
|
342
|
+
console.log('');
|
|
343
|
+
log(colors.bright, '🔍 Analyzing your project...');
|
|
344
|
+
console.log('');
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
const startTime = Date.now();
|
|
348
|
+
analysis = await analyzeProject(targetDir);
|
|
349
|
+
await exportToArchitectureJson(targetDir, analysis);
|
|
350
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
351
|
+
|
|
352
|
+
// Show detected tech stack
|
|
353
|
+
if (analysis.language && analysis.language !== 'unknown') {
|
|
354
|
+
log(colors.cyan, ` Language: ${analysis.language}`);
|
|
355
|
+
if (analysis.primaryLanguage && analysis.primaryLanguage !== analysis.language) {
|
|
356
|
+
log(colors.dim, ` Primary: ${analysis.primaryLanguage}`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (analysis.frameworks.length > 0) {
|
|
361
|
+
log(colors.cyan, ` Frameworks: ${analysis.frameworks.join(', ')}`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (analysis.packageManager && analysis.packageManager !== 'unknown') {
|
|
365
|
+
log(colors.cyan, ` Package Mgr: ${analysis.packageManager}`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (analysis.buildSystem && analysis.buildSystem !== 'unknown') {
|
|
369
|
+
log(colors.cyan, ` Build: ${analysis.buildSystem}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
console.log('');
|
|
373
|
+
|
|
374
|
+
// Show detected domains
|
|
375
|
+
if (analysis.domains.length > 0) {
|
|
376
|
+
log(colors.bright, '📊 Detected domains:');
|
|
377
|
+
console.log('');
|
|
378
|
+
|
|
379
|
+
analysis.domains.slice(0, 5).forEach(domain => {
|
|
380
|
+
const confidence = analysis.domainConfidence[domain] || 0.5;
|
|
381
|
+
const confidenceBar = '█'.repeat(Math.round(confidence * 10)) + '░'.repeat(10 - Math.round(confidence * 10));
|
|
382
|
+
const confidencePct = Math.round(confidence * 100);
|
|
383
|
+
|
|
384
|
+
// Color code based on confidence
|
|
385
|
+
let confidenceColor = colors.red;
|
|
386
|
+
if (confidence >= 0.8) confidenceColor = colors.green;
|
|
387
|
+
else if (confidence >= 0.5) confidenceColor = colors.yellow;
|
|
388
|
+
|
|
389
|
+
log(confidenceColor, ` • ${domain.padEnd(20)} ${confidenceBar} ${confidencePct}%`);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
if (analysis.domains.length > 5) {
|
|
393
|
+
log(colors.dim, ` ... and ${analysis.domains.length - 5} more`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
console.log('');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
log(colors.dim, ` Analysis completed in ${duration}s (${Math.round(analysis.confidence * 100)}% confidence)`);
|
|
400
|
+
|
|
401
|
+
// Show warnings if any
|
|
402
|
+
if (analysis.warnings && analysis.warnings.length > 0) {
|
|
403
|
+
console.log('');
|
|
404
|
+
log(colors.yellow, '⚠️ Warnings:');
|
|
405
|
+
analysis.warnings.slice(0, 3).forEach(warning => {
|
|
406
|
+
log(colors.dim, ` • ${warning}`);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
} catch (error) {
|
|
411
|
+
log(colors.dim, ' ⊙ Smart analysis skipped (project may be empty or unsupported)');
|
|
412
|
+
log(colors.dim, ` Error: ${error.message}`);
|
|
413
|
+
analysis = null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Interactive prompts for generation (if not auto-generated)
|
|
418
|
+
if (analysis && analysis.domains.length > 0 && !autoGenerateDomains && !autoGenerateAgents) {
|
|
419
|
+
console.log('');
|
|
420
|
+
const readline = await import('readline');
|
|
421
|
+
const rl = readline.createInterface({
|
|
422
|
+
input: process.stdin,
|
|
423
|
+
output: process.stdout
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Ask about domain structure
|
|
427
|
+
const generateStructure = await new Promise(resolve => {
|
|
428
|
+
rl.question(`✨ Generate domain structure and specialized agents? [Y/n] `, answer => {
|
|
429
|
+
resolve(answer.toLowerCase() !== 'n');
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
rl.close();
|
|
434
|
+
|
|
435
|
+
if (generateStructure) {
|
|
436
|
+
await generateAgentsAndDomains(targetDir, analysis);
|
|
437
|
+
}
|
|
438
|
+
} else if (autoGenerateDomains || autoGenerateAgents) {
|
|
439
|
+
console.log('');
|
|
440
|
+
log(colors.dim, '🤖 Generating agents and domain structure...');
|
|
441
|
+
await generateAgentsAndDomains(targetDir, analysis, {
|
|
442
|
+
agents: autoGenerateAgents,
|
|
443
|
+
domains: autoGenerateDomains
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
241
447
|
// Done!
|
|
242
448
|
console.log('');
|
|
243
|
-
log(colors.green, '✅
|
|
449
|
+
log(colors.green, '✅ agentful initialized successfully!');
|
|
244
450
|
console.log('');
|
|
451
|
+
|
|
452
|
+
// Determine which structure was created
|
|
453
|
+
const productMdPath = path.join(targetDir, 'PRODUCT.md');
|
|
454
|
+
const claudeProductDir = path.join(targetDir, '.claude/product');
|
|
455
|
+
const usingHierarchical = fs.existsSync(claudeProductDir);
|
|
456
|
+
const usingFlat = fs.existsSync(productMdPath);
|
|
457
|
+
|
|
245
458
|
log(colors.bright, 'Next steps:');
|
|
246
459
|
console.log('');
|
|
247
|
-
console.log(` 1. ${colors.cyan}Edit
|
|
460
|
+
console.log(` 1. ${colors.cyan}Edit your product specification${colors.reset}`);
|
|
461
|
+
|
|
462
|
+
if (usingHierarchical) {
|
|
463
|
+
console.log(` ${colors.green}✓ Created .claude/product/index.md${colors.reset} (hierarchical structure)`);
|
|
464
|
+
console.log(` ${colors.dim}→ Organized by domains (best for larger projects)${colors.reset}`);
|
|
465
|
+
if (analysis && analysis.domains.length > 0) {
|
|
466
|
+
console.log(` ${colors.dim}→ Detected ${analysis.domains.length} domain(s) with pre-configured directories${colors.reset}`);
|
|
467
|
+
}
|
|
468
|
+
} else if (usingFlat) {
|
|
469
|
+
console.log(` ${colors.green}✓ Created PRODUCT.md${colors.reset} (flat structure)`);
|
|
470
|
+
console.log(` ${colors.dim}→ Simple, single-file format (best for small projects)${colors.reset}`);
|
|
471
|
+
}
|
|
472
|
+
|
|
248
473
|
console.log(` 2. ${colors.cyan}Run: claude${colors.reset}`);
|
|
249
|
-
console.log(` 3. ${colors.cyan}Type: /agentful-start${colors.reset}`);
|
|
474
|
+
console.log(` 3. ${colors.cyan}Type: /agentful${colors.reset} (natural) or ${colors.cyan}/agentful-start${colors.reset} (autonomous)`);
|
|
250
475
|
console.log('');
|
|
476
|
+
|
|
477
|
+
if (usingHierarchical) {
|
|
478
|
+
log(colors.dim, '💡 Hierarchical structure benefits:');
|
|
479
|
+
log(colors.dim, ' • Organized by domain (e.g., Auth, Users, Billing)');
|
|
480
|
+
log(colors.dim, ' • Easier to manage large feature sets');
|
|
481
|
+
log(colors.dim, ' • Teams can work on different domains in parallel');
|
|
482
|
+
console.log('');
|
|
483
|
+
}
|
|
484
|
+
|
|
251
485
|
log(colors.dim, 'For autonomous 24/7 development:');
|
|
252
486
|
log(colors.cyan, ` /ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"`);
|
|
253
487
|
console.log('');
|
|
254
488
|
}
|
|
255
489
|
|
|
490
|
+
/**
|
|
491
|
+
* Generate agents and domain structure
|
|
492
|
+
*/
|
|
493
|
+
async function generateAgentsAndDomains(projectPath, analysis, options = {}) {
|
|
494
|
+
const { agents = true, domains = true } = options;
|
|
495
|
+
|
|
496
|
+
try {
|
|
497
|
+
// Generate domain structure
|
|
498
|
+
if (domains) {
|
|
499
|
+
log(colors.dim, '📁 Creating domain structure...');
|
|
500
|
+
const domainGenerator = new DomainStructureGenerator(projectPath, analysis);
|
|
501
|
+
const domainResult = await domainGenerator.generateDomainStructure();
|
|
502
|
+
log(colors.green, ` ✓ Generated ${domainResult.domains} domains with ${domainResult.features} features`);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Generate specialized agents
|
|
506
|
+
if (agents) {
|
|
507
|
+
log(colors.dim, '🤖 Generating specialized agents...');
|
|
508
|
+
const agentGenerator = new AgentGenerator(projectPath, analysis);
|
|
509
|
+
const agentResult = await agentGenerator.generateAgents();
|
|
510
|
+
|
|
511
|
+
const totalAgents = agentResult.core.length + agentResult.domains.length + agentResult.tech.length;
|
|
512
|
+
log(colors.green, ` ✓ Generated ${totalAgents} agents:`);
|
|
513
|
+
log(colors.dim, ` - ${agentResult.core.length} core agents`);
|
|
514
|
+
if (agentResult.domains.length > 0) {
|
|
515
|
+
log(colors.dim, ` - ${agentResult.domains.length} domain agents`);
|
|
516
|
+
}
|
|
517
|
+
if (agentResult.tech.length > 0) {
|
|
518
|
+
log(colors.dim, ` - ${agentResult.tech.length} tech-specific agents`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
console.log('');
|
|
523
|
+
log(colors.green, '✨ Generation complete!');
|
|
524
|
+
log(colors.dim, ' Your agents are now contextually aware of your codebase.');
|
|
525
|
+
} catch (error) {
|
|
526
|
+
log(colors.red, `❌ Generation failed: ${error.message}`);
|
|
527
|
+
log(colors.dim, ' You can continue without it, or run: agentful generate');
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
256
531
|
function showStatus() {
|
|
257
532
|
const agentfulDir = path.join(process.cwd(), '.agentful');
|
|
258
533
|
|
|
259
534
|
if (!fs.existsSync(agentfulDir)) {
|
|
260
|
-
log(colors.red, '❌
|
|
261
|
-
log(colors.dim, 'Run: npx agentful init');
|
|
535
|
+
log(colors.red, '❌ agentful not initialized in this directory!');
|
|
536
|
+
log(colors.dim, 'Run: npx @itz4blitz/agentful init');
|
|
262
537
|
process.exit(1);
|
|
263
538
|
}
|
|
264
539
|
|
|
@@ -471,10 +746,10 @@ async function generateAgents() {
|
|
|
471
746
|
|
|
472
747
|
const agentfulDir = path.join(process.cwd(), '.agentful');
|
|
473
748
|
|
|
474
|
-
// Check if
|
|
749
|
+
// Check if agentful is initialized
|
|
475
750
|
if (!fs.existsSync(agentfulDir)) {
|
|
476
|
-
log(colors.red, '❌
|
|
477
|
-
log(colors.dim, 'Run: npx agentful init');
|
|
751
|
+
log(colors.red, '❌ agentful not initialized in this directory!');
|
|
752
|
+
log(colors.dim, 'Run: npx @itz4blitz/agentful init');
|
|
478
753
|
process.exit(1);
|
|
479
754
|
}
|
|
480
755
|
|
|
@@ -541,7 +816,15 @@ async function main() {
|
|
|
541
816
|
|
|
542
817
|
switch (command) {
|
|
543
818
|
case 'init':
|
|
544
|
-
|
|
819
|
+
// Parse init options
|
|
820
|
+
const initOptions = {
|
|
821
|
+
bare: args.includes('--bare'),
|
|
822
|
+
smart: !args.includes('--no-smart'),
|
|
823
|
+
deep: args.includes('--deep'),
|
|
824
|
+
generateAgents: args.includes('--generate-agents'),
|
|
825
|
+
generateDomains: args.includes('--generate-domains')
|
|
826
|
+
};
|
|
827
|
+
await initagentful(initOptions);
|
|
545
828
|
break;
|
|
546
829
|
|
|
547
830
|
case 'status':
|