@itz4blitz/agentful 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/orchestrator.md +121 -610
- package/.claude/commands/agentful-generate.md +206 -0
- package/.claude/skills/conversation/SKILL.md +152 -975
- package/bin/cli.js +108 -583
- package/bin/hooks/health-check.sh +16 -16
- package/lib/index.js +6 -36
- package/lib/init.js +162 -0
- package/package.json +1 -2
- package/version.json +1 -1
- package/.claude/commands/agentful-agents.md +0 -668
- package/.claude/commands/agentful-skills.md +0 -635
- package/.claude/product/CHANGES.md +0 -276
- package/lib/agent-generator.js +0 -778
- package/lib/domain-detector.js +0 -468
- package/lib/domain-structure-generator.js +0 -770
- package/lib/project-analyzer.js +0 -701
- package/lib/tech-stack-detector.js +0 -1091
- package/lib/template-engine.js +0 -240
- package/templates/agents/domain-agent.template.md +0 -208
- package/templates/agents/tech-agent.template.md +0 -124
|
@@ -8,29 +8,29 @@ set -e
|
|
|
8
8
|
|
|
9
9
|
# Check if .agentful directory exists
|
|
10
10
|
if [ ! -d ".agentful" ]; then
|
|
11
|
-
echo "Agentful not initialized. Run /agentful
|
|
11
|
+
echo "Agentful not initialized. Run: npx @itz4blitz/agentful init"
|
|
12
12
|
exit 0
|
|
13
13
|
fi
|
|
14
14
|
|
|
15
|
-
# Check
|
|
16
|
-
WARNINGS=()
|
|
17
|
-
|
|
15
|
+
# Check if this is a fresh init (no architecture.json means analysis hasn't run)
|
|
18
16
|
if [ ! -f ".agentful/architecture.json" ]; then
|
|
19
|
-
|
|
17
|
+
echo "Agentful initialized but not analyzed."
|
|
18
|
+
echo ""
|
|
19
|
+
echo "Run /agentful-generate to:"
|
|
20
|
+
echo " - Detect your tech stack"
|
|
21
|
+
echo " - Discover business domains"
|
|
22
|
+
echo " - Generate specialized agents and skills"
|
|
23
|
+
exit 0
|
|
20
24
|
fi
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
# Check for generated agents
|
|
27
|
+
AGENT_COUNT=$(find .claude/agents -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
28
|
+
SKILL_COUNT=$(find .claude/skills -name "SKILL.md" 2>/dev/null | wc -l | tr -d ' ')
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
for warning in "${WARNINGS[@]}"; do
|
|
30
|
-
echo " - $warning"
|
|
31
|
-
done
|
|
32
|
-
else
|
|
33
|
-
echo "Agentful ready."
|
|
30
|
+
if [ "$AGENT_COUNT" -lt 3 ] || [ "$SKILL_COUNT" -lt 1 ]; then
|
|
31
|
+
echo "Agentful ready. Consider running /agentful-generate to generate more agents/skills."
|
|
32
|
+
exit 0
|
|
34
33
|
fi
|
|
35
34
|
|
|
35
|
+
echo "Agentful ready."
|
|
36
36
|
exit 0
|
package/lib/index.js
CHANGED
|
@@ -1,40 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* agentful
|
|
5
|
-
* Smart project analysis for autonomous development
|
|
2
|
+
* agentful - Lightweight project initialization
|
|
6
3
|
*
|
|
7
|
-
*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export { detectDomains, getDomainKeywords, getAllDomains, addCustomDomainPattern } from './domain-detector.js';
|
|
12
|
-
export { detectTechStack } from './tech-stack-detector.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Main entry point for project analysis
|
|
16
|
-
* @param {string} projectRoot - Root directory of the project to analyze
|
|
17
|
-
* @returns {Promise<Object>} Comprehensive project analysis
|
|
18
|
-
*/
|
|
19
|
-
export async function analyze(projectRoot) {
|
|
20
|
-
return await analyzeProject(projectRoot);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Quick tech stack detection
|
|
25
|
-
* @param {string} projectRoot - Root directory of the project
|
|
26
|
-
* @returns {Promise<Object>} Detected tech stack
|
|
4
|
+
* The heavy analysis is done by Claude via /agentful-agents and /agentful-skills commands.
|
|
5
|
+
* This module just handles template copying and state management.
|
|
6
|
+
*
|
|
7
|
+
* @module agentful
|
|
27
8
|
*/
|
|
28
|
-
export async function detectStack(projectRoot) {
|
|
29
|
-
return await detectTechStack(projectRoot);
|
|
30
|
-
}
|
|
31
9
|
|
|
32
|
-
|
|
33
|
-
* Domain detection
|
|
34
|
-
* @param {string} projectRoot - Root directory of the project
|
|
35
|
-
* @param {Object} quickScan - Optional quick scan results
|
|
36
|
-
* @returns {Promise<Object>} Detected domains with confidence scores
|
|
37
|
-
*/
|
|
38
|
-
export async function detectBusinessDomains(projectRoot, quickScan) {
|
|
39
|
-
return await detectDomains(projectRoot, quickScan);
|
|
40
|
-
}
|
|
10
|
+
export { initProject, copyDirectory, isInitialized, getState } from './init.js';
|
package/lib/init.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
|
|
7
|
+
const CLAUDE_DIR = path.join(__dirname, '..', '.claude');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initialize agentful in a target project directory
|
|
11
|
+
* @param {string} targetDir - Target project directory
|
|
12
|
+
* @param {Object} options - Initialization options
|
|
13
|
+
* @param {boolean} options.includeProduct - Whether to include PRODUCT.md template
|
|
14
|
+
* @returns {Promise<{success: boolean, files: string[]}>}
|
|
15
|
+
*/
|
|
16
|
+
export async function initProject(targetDir, options = {}) {
|
|
17
|
+
const { includeProduct = false } = options;
|
|
18
|
+
const createdFiles = [];
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Ensure target directory exists
|
|
22
|
+
await fs.access(targetDir);
|
|
23
|
+
|
|
24
|
+
// 1. Copy .claude/ directory (agents, skills, commands)
|
|
25
|
+
const claudeTargetDir = path.join(targetDir, '.claude');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await fs.access(CLAUDE_DIR);
|
|
29
|
+
await copyDirectory(CLAUDE_DIR, claudeTargetDir);
|
|
30
|
+
createdFiles.push('.claude/');
|
|
31
|
+
} catch (err) {
|
|
32
|
+
// .claude directory doesn't exist in package, skip
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 2. Copy CLAUDE.md template
|
|
36
|
+
const claudeMdSource = path.join(TEMPLATE_DIR, 'CLAUDE.md');
|
|
37
|
+
const claudeMdTarget = path.join(targetDir, 'CLAUDE.md');
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await fs.access(claudeMdSource);
|
|
41
|
+
await fs.copyFile(claudeMdSource, claudeMdTarget);
|
|
42
|
+
createdFiles.push('CLAUDE.md');
|
|
43
|
+
} catch (err) {
|
|
44
|
+
// CLAUDE.md template doesn't exist, skip
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Create .agentful/ directory with state files
|
|
48
|
+
const agentfulDir = path.join(targetDir, '.agentful');
|
|
49
|
+
await fs.mkdir(agentfulDir, { recursive: true });
|
|
50
|
+
createdFiles.push('.agentful/');
|
|
51
|
+
|
|
52
|
+
// Create state.json
|
|
53
|
+
const stateFile = path.join(agentfulDir, 'state.json');
|
|
54
|
+
const initialState = {
|
|
55
|
+
initialized: new Date().toISOString(),
|
|
56
|
+
version: '1.0.0',
|
|
57
|
+
agents: [],
|
|
58
|
+
skills: []
|
|
59
|
+
};
|
|
60
|
+
await fs.writeFile(stateFile, JSON.stringify(initialState, null, 2));
|
|
61
|
+
createdFiles.push('.agentful/state.json');
|
|
62
|
+
|
|
63
|
+
// Create completion.json
|
|
64
|
+
const completionFile = path.join(agentfulDir, 'completion.json');
|
|
65
|
+
const initialCompletion = {
|
|
66
|
+
agents: {},
|
|
67
|
+
skills: {},
|
|
68
|
+
lastUpdated: new Date().toISOString()
|
|
69
|
+
};
|
|
70
|
+
await fs.writeFile(completionFile, JSON.stringify(initialCompletion, null, 2));
|
|
71
|
+
createdFiles.push('.agentful/completion.json');
|
|
72
|
+
|
|
73
|
+
// Create decisions.json
|
|
74
|
+
const decisionsFile = path.join(agentfulDir, 'decisions.json');
|
|
75
|
+
const initialDecisions = {
|
|
76
|
+
decisions: [],
|
|
77
|
+
lastUpdated: new Date().toISOString()
|
|
78
|
+
};
|
|
79
|
+
await fs.writeFile(decisionsFile, JSON.stringify(initialDecisions, null, 2));
|
|
80
|
+
createdFiles.push('.agentful/decisions.json');
|
|
81
|
+
|
|
82
|
+
// 4. Optionally copy PRODUCT.md template
|
|
83
|
+
if (includeProduct) {
|
|
84
|
+
const productMdSource = path.join(TEMPLATE_DIR, 'PRODUCT.md');
|
|
85
|
+
const productMdTarget = path.join(targetDir, 'PRODUCT.md');
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
await fs.access(productMdSource);
|
|
89
|
+
await fs.copyFile(productMdSource, productMdTarget);
|
|
90
|
+
createdFiles.push('PRODUCT.md');
|
|
91
|
+
} catch (err) {
|
|
92
|
+
// PRODUCT.md template doesn't exist, skip
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
files: createdFiles
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw new Error(`Failed to initialize project: ${error.message}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Recursively copy a directory
|
|
107
|
+
* @param {string} src - Source directory
|
|
108
|
+
* @param {string} dest - Destination directory
|
|
109
|
+
*/
|
|
110
|
+
export async function copyDirectory(src, dest) {
|
|
111
|
+
// Create destination directory
|
|
112
|
+
await fs.mkdir(dest, { recursive: true });
|
|
113
|
+
|
|
114
|
+
// Read source directory
|
|
115
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
116
|
+
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
const srcPath = path.join(src, entry.name);
|
|
119
|
+
const destPath = path.join(dest, entry.name);
|
|
120
|
+
|
|
121
|
+
if (entry.isDirectory()) {
|
|
122
|
+
// Recursively copy subdirectory
|
|
123
|
+
await copyDirectory(srcPath, destPath);
|
|
124
|
+
} else {
|
|
125
|
+
// Copy file
|
|
126
|
+
await fs.copyFile(srcPath, destPath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if project is already initialized
|
|
133
|
+
* @param {string} targetDir - Target project directory
|
|
134
|
+
* @returns {Promise<boolean>}
|
|
135
|
+
*/
|
|
136
|
+
export async function isInitialized(targetDir) {
|
|
137
|
+
const agentfulDir = path.join(targetDir, '.agentful');
|
|
138
|
+
const stateFile = path.join(agentfulDir, 'state.json');
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
await fs.access(stateFile);
|
|
142
|
+
return true;
|
|
143
|
+
} catch {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get current state from .agentful/state.json
|
|
150
|
+
* @param {string} targetDir - Target project directory
|
|
151
|
+
* @returns {Promise<Object|null>}
|
|
152
|
+
*/
|
|
153
|
+
export async function getState(targetDir) {
|
|
154
|
+
const stateFile = path.join(targetDir, '.agentful', 'state.json');
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const content = await fs.readFile(stateFile, 'utf-8');
|
|
158
|
+
return JSON.parse(content);
|
|
159
|
+
} catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itz4blitz/agentful",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Human-in-the-loop development kit for Claude Code with smart product analysis and natural conversation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"bin/",
|
|
24
24
|
"lib/",
|
|
25
25
|
"template/",
|
|
26
|
-
"templates/",
|
|
27
26
|
".claude/",
|
|
28
27
|
"version.json",
|
|
29
28
|
"LICENSE"
|
package/version.json
CHANGED