@itz4blitz/agentful 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/architect.md +446 -0
- package/.claude/agents/backend.md +251 -0
- package/.claude/agents/fixer.md +263 -0
- package/.claude/agents/frontend.md +351 -0
- package/.claude/agents/orchestrator.md +1139 -0
- package/.claude/agents/reviewer.md +332 -0
- package/.claude/agents/tester.md +319 -0
- package/.claude/commands/agentful-decide.md +139 -0
- package/.claude/commands/agentful-start.md +180 -0
- package/.claude/commands/agentful-status.md +96 -0
- package/.claude/commands/agentful-validate.md +105 -0
- package/.claude/product/CHANGES.md +276 -0
- package/.claude/product/EXAMPLES.md +610 -0
- package/.claude/product/README.md +312 -0
- package/.claude/product/index.md +152 -0
- package/.claude/settings.json +63 -0
- package/.claude/skills/product-tracking/SKILL.md +654 -0
- package/.claude/skills/validation/SKILL.md +271 -0
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/bin/cli.js +580 -0
- package/package.json +42 -0
- package/template/CLAUDE.md +197 -0
- package/template/PRODUCT.md +496 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agentful CLI
|
|
5
|
+
* One-click autonomous product development kit for Claude Code
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
const VERSION = '0.1.0-alpha';
|
|
16
|
+
const AGENTFUL_DIR = path.resolve(__dirname, '..');
|
|
17
|
+
const TEMPLATE_DIR = path.join(AGENTFUL_DIR, 'template');
|
|
18
|
+
|
|
19
|
+
// ANSI colors
|
|
20
|
+
const colors = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
bright: '\x1b[1m',
|
|
23
|
+
dim: '\x1b[2m',
|
|
24
|
+
red: '\x1b[31m',
|
|
25
|
+
green: '\x1b[32m',
|
|
26
|
+
yellow: '\x1b[33m',
|
|
27
|
+
blue: '\x1b[34m',
|
|
28
|
+
magenta: '\x1b[35m',
|
|
29
|
+
cyan: '\x1b[36m',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function log(color, ...args) {
|
|
33
|
+
console.log(color, ...args, colors.reset);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function showBanner() {
|
|
37
|
+
console.log('');
|
|
38
|
+
log(colors.cyan, ' ___ __ ____________ ____ ___ ____________ ');
|
|
39
|
+
log(colors.cyan, ' / | / / / /_ __/ __ \\/ __ \\/ _ | / ____/ _/ / ');
|
|
40
|
+
log(colors.cyan, ' / /| | / / / / / / / /_/ / /_/ / __ |/ / / // / ');
|
|
41
|
+
log(colors.cyan, ' / ___ |/ /_/ / / / / _, _/ _, _/ /_/ / /___/ // / ');
|
|
42
|
+
log(colors.cyan, '/_/ |_|_____/ /_/_/ /_/ |_/_/ |_|\\____/\\____/___/ ');
|
|
43
|
+
console.log('');
|
|
44
|
+
log(colors.dim, ` v${VERSION} `);
|
|
45
|
+
console.log('');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function showHelp() {
|
|
49
|
+
showBanner();
|
|
50
|
+
console.log('USAGE:');
|
|
51
|
+
console.log(` ${colors.bright}agentful${colors.reset} ${colors.green}<command>${colors.reset}`);
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log('COMMANDS:');
|
|
54
|
+
console.log(` ${colors.green}init${colors.reset} Initialize Agentful in current directory`);
|
|
55
|
+
console.log(` ${colors.green}init --bare${colors.reset} Skip creating templates (just .claude/)`);
|
|
56
|
+
console.log(` ${colors.green}generate${colors.reset} Generate specialized agents from tech stack`);
|
|
57
|
+
console.log(` ${colors.green}status${colors.reset} Show current development progress`);
|
|
58
|
+
console.log(` ${colors.green}--help${colors.reset} Show this help message`);
|
|
59
|
+
console.log(` ${colors.green}--version${colors.reset} Show version`);
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log('AFTER INIT:');
|
|
62
|
+
console.log(` 1. Edit ${colors.bright}PRODUCT.md${colors.reset} with your product specification`);
|
|
63
|
+
console.log(` - Define features with priorities: CRITICAL, HIGH, MEDIUM, LOW`);
|
|
64
|
+
console.log(` - Add user stories: "As a [user], I want [feature] so that [benefit]"`);
|
|
65
|
+
console.log(` 2. Run ${colors.bright}claude${colors.reset} to start Claude Code`);
|
|
66
|
+
console.log(` 3. Type ${colors.bright}/agentful-start${colors.reset} to begin autonomous development`);
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log('FOR 24/7 DEVELOPMENT:');
|
|
69
|
+
console.log(` ${colors.cyan}/ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"${colors.reset}`);
|
|
70
|
+
console.log('');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function showVersion() {
|
|
74
|
+
console.log(`Agentful v${VERSION}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function copyDir(src, dest) {
|
|
78
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
79
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
80
|
+
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
const srcPath = path.join(src, entry.name);
|
|
83
|
+
const destPath = path.join(dest, entry.name);
|
|
84
|
+
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
copyDir(srcPath, destPath);
|
|
87
|
+
} else {
|
|
88
|
+
fs.copyFileSync(srcPath, destPath);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function checkGitignore() {
|
|
94
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
95
|
+
let content = '';
|
|
96
|
+
|
|
97
|
+
if (fs.existsSync(gitignorePath)) {
|
|
98
|
+
content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const agentfulIgnore = '# Agentful runtime state\n.agentful/\n';
|
|
102
|
+
|
|
103
|
+
if (!content.includes('.agentful/')) {
|
|
104
|
+
fs.appendFileSync(gitignorePath, agentfulIgnore);
|
|
105
|
+
log(colors.dim, 'Added .agentful/ to .gitignore');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function initAgentful(options = { bare: false }) {
|
|
110
|
+
showBanner();
|
|
111
|
+
|
|
112
|
+
const targetDir = process.cwd();
|
|
113
|
+
const claudeDir = path.join(targetDir, '.claude');
|
|
114
|
+
const agentfulDir = path.join(targetDir, '.agentful');
|
|
115
|
+
|
|
116
|
+
// Check if already initialized
|
|
117
|
+
if (fs.existsSync(claudeDir)) {
|
|
118
|
+
log(colors.yellow, '⚠️ .claude/ directory already exists!');
|
|
119
|
+
const readline = await import('readline');
|
|
120
|
+
const rl = readline.createInterface({
|
|
121
|
+
input: process.stdin,
|
|
122
|
+
output: process.stdout
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const answer = await new Promise(resolve => {
|
|
126
|
+
rl.question('Overwrite? (y/N) ', resolve);
|
|
127
|
+
});
|
|
128
|
+
rl.close();
|
|
129
|
+
|
|
130
|
+
if (answer.toLowerCase() !== 'y') {
|
|
131
|
+
log(colors.dim, 'Aborted.');
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
log(colors.dim, 'Removing existing .claude/...');
|
|
136
|
+
fs.rmSync(claudeDir, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create .claude/ directory structure
|
|
140
|
+
log(colors.dim, 'Creating .claude/ directory structure...');
|
|
141
|
+
|
|
142
|
+
const sourceClaudeDir = path.join(AGENTFUL_DIR, '.claude');
|
|
143
|
+
copyDir(sourceClaudeDir, claudeDir);
|
|
144
|
+
|
|
145
|
+
// Create .agentful/ directory
|
|
146
|
+
if (!fs.existsSync(agentfulDir)) {
|
|
147
|
+
fs.mkdirSync(agentfulDir, { recursive: true });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Initialize state files
|
|
151
|
+
log(colors.dim, 'Initializing state files...');
|
|
152
|
+
|
|
153
|
+
const now = new Date().toISOString();
|
|
154
|
+
|
|
155
|
+
fs.writeFileSync(
|
|
156
|
+
path.join(agentfulDir, 'state.json'),
|
|
157
|
+
JSON.stringify(
|
|
158
|
+
{
|
|
159
|
+
version: '0.1.0',
|
|
160
|
+
current_task: null,
|
|
161
|
+
current_phase: 'idle',
|
|
162
|
+
iterations: 0,
|
|
163
|
+
last_updated: now,
|
|
164
|
+
blocked_on: []
|
|
165
|
+
},
|
|
166
|
+
null,
|
|
167
|
+
2
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
fs.writeFileSync(
|
|
172
|
+
path.join(agentfulDir, 'decisions.json'),
|
|
173
|
+
JSON.stringify({ pending: [], resolved: [] }, null, 2)
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
fs.writeFileSync(
|
|
177
|
+
path.join(agentfulDir, 'completion.json'),
|
|
178
|
+
JSON.stringify(
|
|
179
|
+
{
|
|
180
|
+
features: {},
|
|
181
|
+
gates: {
|
|
182
|
+
tests_passing: false,
|
|
183
|
+
no_type_errors: false,
|
|
184
|
+
no_dead_code: false,
|
|
185
|
+
coverage_80: false,
|
|
186
|
+
security_clean: false
|
|
187
|
+
},
|
|
188
|
+
overall: 0,
|
|
189
|
+
last_updated: now
|
|
190
|
+
},
|
|
191
|
+
null,
|
|
192
|
+
2
|
|
193
|
+
)
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
fs.writeFileSync(
|
|
197
|
+
path.join(agentfulDir, 'architecture.json'),
|
|
198
|
+
JSON.stringify(
|
|
199
|
+
{
|
|
200
|
+
detected_stack: {},
|
|
201
|
+
generated_agents: [],
|
|
202
|
+
decisions: [],
|
|
203
|
+
timestamp: now
|
|
204
|
+
},
|
|
205
|
+
null,
|
|
206
|
+
2
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Copy templates if not bare mode
|
|
211
|
+
if (!options.bare) {
|
|
212
|
+
log(colors.dim, 'Creating template files...');
|
|
213
|
+
|
|
214
|
+
const claudeMdPath = path.join(targetDir, 'CLAUDE.md');
|
|
215
|
+
const productMdPath = path.join(targetDir, 'PRODUCT.md');
|
|
216
|
+
|
|
217
|
+
if (!fs.existsSync(claudeMdPath)) {
|
|
218
|
+
fs.copyFileSync(
|
|
219
|
+
path.join(TEMPLATE_DIR, 'CLAUDE.md'),
|
|
220
|
+
claudeMdPath
|
|
221
|
+
);
|
|
222
|
+
log(colors.green, ' ✓ Created CLAUDE.md');
|
|
223
|
+
} else {
|
|
224
|
+
log(colors.dim, ' ⊙ CLAUDE.md already exists, skipping');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (!fs.existsSync(productMdPath)) {
|
|
228
|
+
fs.copyFileSync(
|
|
229
|
+
path.join(TEMPLATE_DIR, 'PRODUCT.md'),
|
|
230
|
+
productMdPath
|
|
231
|
+
);
|
|
232
|
+
log(colors.green, ' ✓ Created PRODUCT.md');
|
|
233
|
+
} else {
|
|
234
|
+
log(colors.dim, ' ⊙ PRODUCT.md already exists, skipping');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Update .gitignore
|
|
239
|
+
checkGitignore();
|
|
240
|
+
|
|
241
|
+
// Done!
|
|
242
|
+
console.log('');
|
|
243
|
+
log(colors.green, '✅ Agentful initialized successfully!');
|
|
244
|
+
console.log('');
|
|
245
|
+
log(colors.bright, 'Next steps:');
|
|
246
|
+
console.log('');
|
|
247
|
+
console.log(` 1. ${colors.cyan}Edit PRODUCT.md${colors.reset} with your product specification`);
|
|
248
|
+
console.log(` 2. ${colors.cyan}Run: claude${colors.reset}`);
|
|
249
|
+
console.log(` 3. ${colors.cyan}Type: /agentful-start${colors.reset}`);
|
|
250
|
+
console.log('');
|
|
251
|
+
log(colors.dim, 'For autonomous 24/7 development:');
|
|
252
|
+
log(colors.cyan, ` /ralph-loop "/agentful-start" --max-iterations 50 --completion-promise "AGENTFUL_COMPLETE"`);
|
|
253
|
+
console.log('');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function showStatus() {
|
|
257
|
+
const agentfulDir = path.join(process.cwd(), '.agentful');
|
|
258
|
+
|
|
259
|
+
if (!fs.existsSync(agentfulDir)) {
|
|
260
|
+
log(colors.red, '❌ Agentful not initialized in this directory!');
|
|
261
|
+
log(colors.dim, 'Run: npx agentful init');
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const statePath = path.join(agentfulDir, 'state.json');
|
|
266
|
+
const completionPath = path.join(agentfulDir, 'completion.json');
|
|
267
|
+
const decisionsPath = path.join(agentfulDir, 'decisions.json');
|
|
268
|
+
|
|
269
|
+
if (!fs.existsSync(statePath)) {
|
|
270
|
+
log(colors.red, '❌ State file missing!');
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const state = JSON.parse(fs.readFileSync(statePath, 'utf-8'));
|
|
275
|
+
const completion = fs.existsSync(completionPath)
|
|
276
|
+
? JSON.parse(fs.readFileSync(completionPath, 'utf-8'))
|
|
277
|
+
: null;
|
|
278
|
+
const decisions = fs.existsSync(decisionsPath)
|
|
279
|
+
? JSON.parse(fs.readFileSync(decisionsPath, 'utf-8'))
|
|
280
|
+
: null;
|
|
281
|
+
|
|
282
|
+
showBanner();
|
|
283
|
+
|
|
284
|
+
log(colors.bright, 'Current Status:');
|
|
285
|
+
console.log('');
|
|
286
|
+
|
|
287
|
+
// Show current work
|
|
288
|
+
if (state.current_task) {
|
|
289
|
+
log(colors.blue, `🔧 Working on: ${colors.reset}${state.current_task}`);
|
|
290
|
+
log(colors.dim, ` Phase: ${state.current_phase}`);
|
|
291
|
+
log(colors.dim, ` Iterations: ${state.iterations}`);
|
|
292
|
+
} else {
|
|
293
|
+
log(colors.dim, '💤 Idle - no active task');
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
console.log('');
|
|
297
|
+
|
|
298
|
+
// Show completion if available
|
|
299
|
+
if (completion) {
|
|
300
|
+
const percentage = completion.overall || 0;
|
|
301
|
+
const filled = Math.round(percentage / 5);
|
|
302
|
+
const bar = '█'.repeat(filled) + '░'.repeat(20 - filled);
|
|
303
|
+
|
|
304
|
+
log(colors.bright, 'Progress:');
|
|
305
|
+
log(colors.cyan, ` ${bar} ${percentage}%`);
|
|
306
|
+
console.log('');
|
|
307
|
+
|
|
308
|
+
// Show quality gates
|
|
309
|
+
if (completion.gates) {
|
|
310
|
+
log(colors.bright, 'Quality Gates:');
|
|
311
|
+
Object.entries(completion.gates).forEach(([gate, passed]) => {
|
|
312
|
+
const icon = passed ? '✅' : '❌';
|
|
313
|
+
const label = gate.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
|
|
314
|
+
log(passed ? colors.green : colors.red, ` ${icon} ${label}`);
|
|
315
|
+
});
|
|
316
|
+
console.log('');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Show pending decisions
|
|
320
|
+
if (decisions && decisions.pending && decisions.pending.length > 0) {
|
|
321
|
+
log(colors.yellow, `⚠️ ${decisions.pending.length} pending decisions:`);
|
|
322
|
+
decisions.pending.forEach((d, i) => {
|
|
323
|
+
log(colors.dim, ` ${i + 1}. ${d.question}`);
|
|
324
|
+
});
|
|
325
|
+
console.log('');
|
|
326
|
+
log(colors.cyan, ` Run: /agentful-decide`);
|
|
327
|
+
console.log('');
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Show next action
|
|
332
|
+
log(colors.bright, 'Next Actions:');
|
|
333
|
+
log(colors.cyan, ' • /agentful-start - Continue development');
|
|
334
|
+
log(colors.cyan, ' • /agentful-decide - Answer pending decisions');
|
|
335
|
+
log(colors.cyan, ' • /agentful-validate- Run quality checks');
|
|
336
|
+
console.log('');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function detectTechStack() {
|
|
340
|
+
const targetDir = process.cwd();
|
|
341
|
+
const detected = {
|
|
342
|
+
language: null,
|
|
343
|
+
framework: null,
|
|
344
|
+
dependencies: [],
|
|
345
|
+
devDependencies: []
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
// Check for package.json (Node.js/JavaScript/TypeScript)
|
|
349
|
+
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
350
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
351
|
+
try {
|
|
352
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
353
|
+
detected.dependencies = Object.keys(pkg.dependencies || {});
|
|
354
|
+
detected.devDependencies = Object.keys(pkg.devDependencies || {});
|
|
355
|
+
detected.language = pkg.type === 'module' ? 'TypeScript/ESM' : 'JavaScript/TypeScript';
|
|
356
|
+
|
|
357
|
+
// Detect framework
|
|
358
|
+
if (detected.dependencies.includes('next')) {
|
|
359
|
+
detected.framework = 'Next.js';
|
|
360
|
+
} else if (detected.dependencies.includes('react')) {
|
|
361
|
+
detected.framework = 'React';
|
|
362
|
+
} else if (detected.dependencies.includes('vue')) {
|
|
363
|
+
detected.framework = 'Vue';
|
|
364
|
+
} else if (detected.dependencies.includes('express')) {
|
|
365
|
+
detected.framework = 'Express';
|
|
366
|
+
} else if (detected.dependencies.includes('nestjs')) {
|
|
367
|
+
detected.framework = 'NestJS';
|
|
368
|
+
}
|
|
369
|
+
} catch (err) {
|
|
370
|
+
log(colors.yellow, '⚠️ Could not parse package.json');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Check for requirements.txt or pyproject.toml (Python)
|
|
375
|
+
const requirementsPath = path.join(targetDir, 'requirements.txt');
|
|
376
|
+
const pyprojectPath = path.join(targetDir, 'pyproject.toml');
|
|
377
|
+
if (fs.existsSync(requirementsPath) || fs.existsSync(pyprojectPath)) {
|
|
378
|
+
detected.language = 'Python';
|
|
379
|
+
const requirements = fs.existsSync(requirementsPath)
|
|
380
|
+
? fs.readFileSync(requirementsPath, 'utf-8')
|
|
381
|
+
: '';
|
|
382
|
+
if (requirements.includes('django')) detected.framework = 'Django';
|
|
383
|
+
else if (requirements.includes('flask')) detected.framework = 'Flask';
|
|
384
|
+
else if (requirements.includes('fastapi')) detected.framework = 'FastAPI';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Check for go.mod (Go)
|
|
388
|
+
if (fs.existsSync(path.join(targetDir, 'go.mod'))) {
|
|
389
|
+
detected.language = 'Go';
|
|
390
|
+
detected.framework = 'Standard Library';
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Check for Cargo.toml (Rust)
|
|
394
|
+
if (fs.existsSync(path.join(targetDir, 'Cargo.toml'))) {
|
|
395
|
+
detected.language = 'Rust';
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Check for .csproj or .fsproj (C#/.NET)
|
|
399
|
+
const csprojFiles = fs.readdirSync(targetDir).filter(f => f.endsWith('.csproj'));
|
|
400
|
+
if (csprojFiles.length > 0) {
|
|
401
|
+
detected.language = 'C#';
|
|
402
|
+
detected.framework = 'ASP.NET';
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Check for pom.xml (Java)
|
|
406
|
+
if (fs.existsSync(path.join(targetDir, 'pom.xml'))) {
|
|
407
|
+
detected.language = 'Java';
|
|
408
|
+
detected.framework = 'Maven';
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return detected;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function generateAgentPrompt(stack) {
|
|
415
|
+
let prompt = `# Tech Stack Analysis\n\n`;
|
|
416
|
+
prompt += `**Language**: ${stack.language || 'Unknown'}\n`;
|
|
417
|
+
prompt += `**Framework**: ${stack.framework || 'None'}\n\n`;
|
|
418
|
+
|
|
419
|
+
if (stack.dependencies.length > 0) {
|
|
420
|
+
prompt += `**Key Dependencies**:\n`;
|
|
421
|
+
stack.dependencies.slice(0, 10).forEach(dep => {
|
|
422
|
+
prompt += `- ${dep}\n`;
|
|
423
|
+
});
|
|
424
|
+
prompt += `\n`;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
prompt += `## Instructions\n\n`;
|
|
428
|
+
prompt += `You are the Architect agent. Your task is to:\n\n`;
|
|
429
|
+
prompt += `1. **Sample 3-5 files** from the codebase to understand patterns\n`;
|
|
430
|
+
prompt += `2. **Detect conventions**: file structure, naming, imports, styling\n`;
|
|
431
|
+
prompt += `3. **Generate specialized agents** with real examples from the code\n\n`;
|
|
432
|
+
prompt += `## Output\n\n`;
|
|
433
|
+
prompt += `Create/update \`.agentful/architecture.json\` with:\n`;
|
|
434
|
+
prompt += `- Detected patterns\n`;
|
|
435
|
+
prompt += `- Generated agent list\n`;
|
|
436
|
+
prompt += `- Key conventions\n\n`;
|
|
437
|
+
prompt += `Then create project-specific agent files in \`.claude/agents/\` \n`;
|
|
438
|
+
prompt += `using the naming convention: \`[tech]-specialist.md\`\n\n`;
|
|
439
|
+
|
|
440
|
+
prompt += `## Example Agent Template\n\n`;
|
|
441
|
+
prompt += `\`\`\`markdown\n`;
|
|
442
|
+
prompt += `# [Tech] Specialist Agent\n\n`;
|
|
443
|
+
prompt += `---\n`;
|
|
444
|
+
prompt += `name: [tech]-specialist\n`;
|
|
445
|
+
prompt += `description: Expert in [Tech] development patterns\n`;
|
|
446
|
+
prompt += `model: sonnet\n\n`;
|
|
447
|
+
prompt += `## Context\n\n`;
|
|
448
|
+
prompt += `[Analyze actual code samples and list real patterns]\n\n`;
|
|
449
|
+
prompt += `## Conventions\n\n`;
|
|
450
|
+
prompt += `1. [Pattern from actual code]\n`;
|
|
451
|
+
prompt += `2. [Pattern from actual code]\n`;
|
|
452
|
+
prompt += `3. [Pattern from actual code]\n\n`;
|
|
453
|
+
prompt += `## Examples from Codebase\n\n`;
|
|
454
|
+
prompt += `\`\`\`[language]\n`;
|
|
455
|
+
prompt += `[Real example from sampled files]\n`;
|
|
456
|
+
prompt += `\`\`\`\n`;
|
|
457
|
+
prompt += `\`\`\`\n\n`;
|
|
458
|
+
|
|
459
|
+
prompt += `---\n\n`;
|
|
460
|
+
prompt += `**IMPORTANT**: \n`;
|
|
461
|
+
prompt += `- Sample REAL files, don't make up patterns\n`;
|
|
462
|
+
prompt += `- Include ACTUAL code examples from this project\n`;
|
|
463
|
+
prompt += `- Respect existing conventions, don't introduce new ones\n`;
|
|
464
|
+
prompt += `- Generate agents ONLY for technologies actually in use\n`;
|
|
465
|
+
|
|
466
|
+
return prompt;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
async function generateAgents() {
|
|
470
|
+
showBanner();
|
|
471
|
+
|
|
472
|
+
const agentfulDir = path.join(process.cwd(), '.agentful');
|
|
473
|
+
|
|
474
|
+
// Check if Agentful is initialized
|
|
475
|
+
if (!fs.existsSync(agentfulDir)) {
|
|
476
|
+
log(colors.red, '❌ Agentful not initialized in this directory!');
|
|
477
|
+
log(colors.dim, 'Run: npx agentful init');
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Detect tech stack
|
|
482
|
+
log(colors.dim, 'Analyzing tech stack...');
|
|
483
|
+
const stack = detectTechStack();
|
|
484
|
+
|
|
485
|
+
if (!stack.language) {
|
|
486
|
+
log(colors.yellow, '⚠️ Could not detect language/framework');
|
|
487
|
+
log(colors.dim, 'Supported: Node.js, Python, Go, Rust, C#, Java');
|
|
488
|
+
console.log('');
|
|
489
|
+
log(colors.cyan, 'Manually trigger architect analysis by running:');
|
|
490
|
+
log(colors.cyan, ' claude');
|
|
491
|
+
log(colors.cyan, ' Then invoke the architect agent');
|
|
492
|
+
console.log('');
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
log(colors.green, `✓ Detected: ${stack.language} ${stack.framework ? `(${stack.framework})` : ''}`);
|
|
497
|
+
log(colors.dim, ` Dependencies: ${stack.dependencies.length} packages`);
|
|
498
|
+
|
|
499
|
+
// Update architecture.json
|
|
500
|
+
log(colors.dim, 'Updating architecture analysis...');
|
|
501
|
+
const archPath = path.join(agentfulDir, 'architecture.json');
|
|
502
|
+
let architecture = { detected_stack: {}, generated_agents: [], decisions: [], timestamp: new Date().toISOString() };
|
|
503
|
+
|
|
504
|
+
if (fs.existsSync(archPath)) {
|
|
505
|
+
architecture = JSON.parse(fs.readFileSync(archPath, 'utf-8'));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
architecture.detected_stack = stack;
|
|
509
|
+
architecture.timestamp = new Date().toISOString();
|
|
510
|
+
|
|
511
|
+
fs.writeFileSync(archPath, JSON.stringify(architecture, null, 2));
|
|
512
|
+
|
|
513
|
+
console.log('');
|
|
514
|
+
log(colors.bright, 'Tech Stack Analysis Complete!');
|
|
515
|
+
console.log('');
|
|
516
|
+
|
|
517
|
+
log(colors.bright, 'Detected Stack:');
|
|
518
|
+
if (stack.language) log(colors.cyan, ` Language: ${stack.language}`);
|
|
519
|
+
if (stack.framework) log(colors.cyan, ` Framework: ${stack.framework}`);
|
|
520
|
+
if (stack.dependencies.length > 0) {
|
|
521
|
+
log(colors.cyan, ` Dependencies: ${stack.dependencies.length} packages`);
|
|
522
|
+
}
|
|
523
|
+
console.log('');
|
|
524
|
+
|
|
525
|
+
log(colors.bright, 'Next Steps:');
|
|
526
|
+
console.log('');
|
|
527
|
+
log(colors.cyan, ' 1. Review .agentful/architecture.json');
|
|
528
|
+
log(colors.cyan, ' 2. Run: claude');
|
|
529
|
+
log(colors.cyan, ' 3. Type: /agentful-start');
|
|
530
|
+
log(colors.cyan, ' (Architect agent will generate specialized agents automatically)');
|
|
531
|
+
console.log('');
|
|
532
|
+
|
|
533
|
+
log(colors.dim, '💡 Tip: Architect generates project-specific agents on first /agentful-start run');
|
|
534
|
+
console.log('');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Main CLI
|
|
538
|
+
async function main() {
|
|
539
|
+
const args = process.argv.slice(2);
|
|
540
|
+
const command = args[0];
|
|
541
|
+
|
|
542
|
+
switch (command) {
|
|
543
|
+
case 'init':
|
|
544
|
+
await initAgentful({ bare: args.includes('--bare') });
|
|
545
|
+
break;
|
|
546
|
+
|
|
547
|
+
case 'status':
|
|
548
|
+
showStatus();
|
|
549
|
+
break;
|
|
550
|
+
|
|
551
|
+
case 'generate':
|
|
552
|
+
await generateAgents();
|
|
553
|
+
break;
|
|
554
|
+
|
|
555
|
+
case '--help':
|
|
556
|
+
case '-h':
|
|
557
|
+
case 'help':
|
|
558
|
+
showHelp();
|
|
559
|
+
break;
|
|
560
|
+
|
|
561
|
+
case '--version':
|
|
562
|
+
case '-v':
|
|
563
|
+
showVersion();
|
|
564
|
+
break;
|
|
565
|
+
|
|
566
|
+
default:
|
|
567
|
+
if (!command || command.startsWith('-')) {
|
|
568
|
+
showHelp();
|
|
569
|
+
} else {
|
|
570
|
+
log(colors.red, `Unknown command: ${command}`);
|
|
571
|
+
log(colors.dim, 'Run: agentful --help');
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
main().catch(err => {
|
|
578
|
+
log(colors.red, 'Error:', err.message);
|
|
579
|
+
process.exit(1);
|
|
580
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@itz4blitz/agentful",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One-click autonomous product development kit for Claude Code (Alpha - Unstable)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agentful": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"init": "node bin/cli.js init",
|
|
11
|
+
"release": "semantic-release",
|
|
12
|
+
"release:dry-run": "semantic-release --dry-run",
|
|
13
|
+
"docs:dev": "vocs dev",
|
|
14
|
+
"docs:build": "vocs build",
|
|
15
|
+
"docs:preview": "vocs preview"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin/",
|
|
19
|
+
"template/",
|
|
20
|
+
".claude/"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude-code",
|
|
24
|
+
"autonomous",
|
|
25
|
+
"ai-development",
|
|
26
|
+
"agent",
|
|
27
|
+
"productivity"
|
|
28
|
+
],
|
|
29
|
+
"author": "Agentful",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/itz4blitz/agentful.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://agentful.app",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"vocs": "^1.4.1"
|
|
41
|
+
}
|
|
42
|
+
}
|