devflow-agents 0.7.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/commands/agents/architect.md +1162 -0
- package/.claude/commands/agents/architect.meta.yaml +124 -0
- package/.claude/commands/agents/builder.md +1432 -0
- package/.claude/commands/agents/builder.meta.yaml +117 -0
- package/.claude/commands/agents/chronicler.md +633 -0
- package/.claude/commands/agents/chronicler.meta.yaml +217 -0
- package/.claude/commands/agents/guardian.md +456 -0
- package/.claude/commands/agents/guardian.meta.yaml +127 -0
- package/.claude/commands/agents/strategist.md +483 -0
- package/.claude/commands/agents/strategist.meta.yaml +158 -0
- package/.claude/commands/agents/system-designer.md +1137 -0
- package/.claude/commands/agents/system-designer.meta.yaml +156 -0
- package/.claude/commands/devflow-help.md +93 -0
- package/.claude/commands/devflow-status.md +60 -0
- package/.claude/commands/quick/create-adr.md +82 -0
- package/.claude/commands/quick/new-feature.md +57 -0
- package/.claude/commands/quick/security-check.md +54 -0
- package/.claude/commands/quick/system-design.md +58 -0
- package/.claude_project +52 -0
- package/.devflow/agents/architect.meta.yaml +122 -0
- package/.devflow/agents/builder.meta.yaml +116 -0
- package/.devflow/agents/chronicler.meta.yaml +222 -0
- package/.devflow/agents/guardian.meta.yaml +127 -0
- package/.devflow/agents/strategist.meta.yaml +158 -0
- package/.devflow/agents/system-designer.meta.yaml +265 -0
- package/.devflow/project.yaml +242 -0
- package/.gitignore-template +83 -0
- package/LICENSE +21 -0
- package/README.md +244 -0
- package/bin/devflow.js +32 -0
- package/lib/constants.js +75 -0
- package/lib/init.js +162 -0
- package/lib/update.js +181 -0
- package/lib/utils.js +157 -0
- package/package.json +46 -0
package/lib/update.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const {
|
|
4
|
+
VERSION,
|
|
5
|
+
PACKAGE_ROOT,
|
|
6
|
+
BASE_DIRS,
|
|
7
|
+
DOCS_DIRS,
|
|
8
|
+
GITKEEP_DIRS,
|
|
9
|
+
} = require('./constants');
|
|
10
|
+
const {
|
|
11
|
+
printHeader,
|
|
12
|
+
success,
|
|
13
|
+
error,
|
|
14
|
+
warn,
|
|
15
|
+
info,
|
|
16
|
+
printUpdateSuccess,
|
|
17
|
+
confirm,
|
|
18
|
+
copyDir,
|
|
19
|
+
copyFile,
|
|
20
|
+
ensureDirs,
|
|
21
|
+
createGitkeep,
|
|
22
|
+
pathExists,
|
|
23
|
+
resolveTarget,
|
|
24
|
+
} = require('./utils');
|
|
25
|
+
|
|
26
|
+
async function updateCommand(targetArg, options) {
|
|
27
|
+
printHeader(VERSION);
|
|
28
|
+
|
|
29
|
+
const targetDir = resolveTarget(targetArg);
|
|
30
|
+
|
|
31
|
+
// 1. Verify DevFlow is installed
|
|
32
|
+
const hasAgents = await pathExists(path.join(targetDir, '.claude', 'commands', 'agents'));
|
|
33
|
+
const hasDevflow = await pathExists(path.join(targetDir, '.devflow'));
|
|
34
|
+
|
|
35
|
+
if (!hasAgents && !hasDevflow) {
|
|
36
|
+
error(`DevFlow not found in: ${targetDir}`);
|
|
37
|
+
info('Use "devflow init" to install for the first time.');
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Read installed version
|
|
42
|
+
let installedVersion = 'unknown';
|
|
43
|
+
const projectYamlPath = path.join(targetDir, '.devflow', 'project.yaml');
|
|
44
|
+
try {
|
|
45
|
+
const content = await fs.promises.readFile(projectYamlPath, 'utf8');
|
|
46
|
+
const match = content.match(/^\s*version:\s*"?([^"\s]+)"?/m);
|
|
47
|
+
if (match) installedVersion = match[1];
|
|
48
|
+
} catch { /* file may not exist */ }
|
|
49
|
+
|
|
50
|
+
info(`Project: ${targetDir}`);
|
|
51
|
+
info(`Installed version: ${installedVersion}`);
|
|
52
|
+
info(`New version: ${VERSION}`);
|
|
53
|
+
console.log();
|
|
54
|
+
|
|
55
|
+
// 3. Check if already up to date
|
|
56
|
+
if (installedVersion === VERSION) {
|
|
57
|
+
success('DevFlow is already up to date!');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 4. Confirm update
|
|
62
|
+
if (!options.force) {
|
|
63
|
+
warn('The update will overwrite agent files.');
|
|
64
|
+
warn('Customizations in .claude/commands/agents/ will be lost.');
|
|
65
|
+
console.log();
|
|
66
|
+
const shouldContinue = await confirm('Continue with update?');
|
|
67
|
+
if (!shouldContinue) {
|
|
68
|
+
warn('Update cancelled.');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log();
|
|
74
|
+
info('Updating DevFlow...');
|
|
75
|
+
console.log();
|
|
76
|
+
|
|
77
|
+
// 5. Backup existing agents
|
|
78
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
79
|
+
const backupDir = path.join(targetDir, '.devflow', `backup-${timestamp}`);
|
|
80
|
+
await fs.promises.mkdir(backupDir, { recursive: true });
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
await fs.promises.cp(
|
|
84
|
+
path.join(targetDir, '.claude', 'commands', 'agents'),
|
|
85
|
+
path.join(backupDir, 'agents'),
|
|
86
|
+
{ recursive: true }
|
|
87
|
+
);
|
|
88
|
+
} catch { /* may not exist */ }
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await fs.promises.copyFile(
|
|
92
|
+
projectYamlPath,
|
|
93
|
+
path.join(backupDir, 'project.yaml')
|
|
94
|
+
);
|
|
95
|
+
} catch { /* may not exist */ }
|
|
96
|
+
|
|
97
|
+
success(`Backup created: .devflow/${path.basename(backupDir)}/`);
|
|
98
|
+
|
|
99
|
+
// 6. Update agents
|
|
100
|
+
console.log(' \u2192 Updating agents...');
|
|
101
|
+
await copyDir(
|
|
102
|
+
path.join(PACKAGE_ROOT, '.claude', 'commands', 'agents'),
|
|
103
|
+
path.join(targetDir, '.claude', 'commands', 'agents')
|
|
104
|
+
);
|
|
105
|
+
success('Agents updated (.claude/commands/agents/)');
|
|
106
|
+
|
|
107
|
+
// 7. Update quick commands
|
|
108
|
+
console.log(' \u2192 Updating quick commands...');
|
|
109
|
+
await copyDir(
|
|
110
|
+
path.join(PACKAGE_ROOT, '.claude', 'commands', 'quick'),
|
|
111
|
+
path.join(targetDir, '.claude', 'commands', 'quick')
|
|
112
|
+
);
|
|
113
|
+
success('Quick commands updated');
|
|
114
|
+
|
|
115
|
+
// 8. Update help & status commands
|
|
116
|
+
console.log(' \u2192 Updating help & status commands...');
|
|
117
|
+
for (const file of ['devflow-help.md', 'devflow-status.md']) {
|
|
118
|
+
try {
|
|
119
|
+
await copyFile(
|
|
120
|
+
path.join(PACKAGE_ROOT, '.claude', 'commands', file),
|
|
121
|
+
path.join(targetDir, '.claude', 'commands', file)
|
|
122
|
+
);
|
|
123
|
+
} catch { /* skip if missing */ }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 9. Update .claude_project
|
|
127
|
+
console.log(' \u2192 Updating .claude_project...');
|
|
128
|
+
await copyFile(
|
|
129
|
+
path.join(PACKAGE_ROOT, '.claude_project'),
|
|
130
|
+
path.join(targetDir, '.claude_project')
|
|
131
|
+
);
|
|
132
|
+
success('.claude_project updated');
|
|
133
|
+
|
|
134
|
+
// 10. Update .devflow/agents/ meta.yaml files
|
|
135
|
+
console.log(' \u2192 Updating .devflow/agents/ meta.yaml files...');
|
|
136
|
+
await copyDir(
|
|
137
|
+
path.join(PACKAGE_ROOT, '.devflow', 'agents'),
|
|
138
|
+
path.join(targetDir, '.devflow', 'agents')
|
|
139
|
+
);
|
|
140
|
+
success('.devflow/agents/ updated');
|
|
141
|
+
|
|
142
|
+
// 11. Update project.yaml version
|
|
143
|
+
console.log(' \u2192 Updating project.yaml version...');
|
|
144
|
+
try {
|
|
145
|
+
let content = await fs.promises.readFile(projectYamlPath, 'utf8');
|
|
146
|
+
content = content.replace(
|
|
147
|
+
/version:\s*"?[^"\s]+"?/,
|
|
148
|
+
`version: "${VERSION}"`
|
|
149
|
+
);
|
|
150
|
+
await fs.promises.writeFile(projectYamlPath, content, 'utf8');
|
|
151
|
+
success(`project.yaml version updated to ${VERSION}`);
|
|
152
|
+
} catch {
|
|
153
|
+
await copyFile(
|
|
154
|
+
path.join(PACKAGE_ROOT, '.devflow', 'project.yaml'),
|
|
155
|
+
projectYamlPath
|
|
156
|
+
);
|
|
157
|
+
success('project.yaml created');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 12. Ensure directory structure is complete
|
|
161
|
+
console.log(' \u2192 Verifying directory structure...');
|
|
162
|
+
await ensureDirs(targetDir, [...BASE_DIRS, ...DOCS_DIRS]);
|
|
163
|
+
await createGitkeep(targetDir, GITKEEP_DIRS);
|
|
164
|
+
success('Directory structure verified');
|
|
165
|
+
|
|
166
|
+
// 13. Success output
|
|
167
|
+
printUpdateSuccess(VERSION);
|
|
168
|
+
info('What was updated:');
|
|
169
|
+
console.log(' \u2022 Agents in .claude/commands/agents/');
|
|
170
|
+
console.log(' \u2022 Quick commands in .claude/commands/quick/');
|
|
171
|
+
console.log(' \u2022 .claude_project orchestration rules');
|
|
172
|
+
console.log(' \u2022 .devflow/agents/ meta.yaml files');
|
|
173
|
+
console.log(' \u2022 Directory structure');
|
|
174
|
+
console.log();
|
|
175
|
+
info(`Backup saved in: .devflow/${path.basename(backupDir)}/`);
|
|
176
|
+
console.log();
|
|
177
|
+
info('Tip: Use /agents:strategist to start a new feature');
|
|
178
|
+
console.log();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = { updateCommand };
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const { execSync } = require('node:child_process');
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const readline = require('node:readline');
|
|
5
|
+
|
|
6
|
+
// ANSI color helpers (no chalk dependency)
|
|
7
|
+
const c = {
|
|
8
|
+
red: (s) => `\x1b[0;31m${s}\x1b[0m`,
|
|
9
|
+
green: (s) => `\x1b[0;32m${s}\x1b[0m`,
|
|
10
|
+
yellow: (s) => `\x1b[1;33m${s}\x1b[0m`,
|
|
11
|
+
blue: (s) => `\x1b[0;34m${s}\x1b[0m`,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function printHeader(version) {
|
|
15
|
+
const line = c.blue('\u2501'.repeat(55));
|
|
16
|
+
console.log(line);
|
|
17
|
+
console.log(c.blue(` DevFlow CLI v${version}`));
|
|
18
|
+
console.log(line);
|
|
19
|
+
console.log();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function success(msg) { console.log(`${c.green('\u2713')} ${msg}`); }
|
|
23
|
+
function error(msg) { console.log(`${c.red('\u2717')} ${msg}`); }
|
|
24
|
+
function warn(msg) { console.log(`${c.yellow('\u26A0')} ${msg}`); }
|
|
25
|
+
function info(msg) { console.log(`${c.blue('\u2139')} ${msg}`); }
|
|
26
|
+
|
|
27
|
+
function printSuccess(version) {
|
|
28
|
+
const line = c.green('\u2501'.repeat(55));
|
|
29
|
+
console.log();
|
|
30
|
+
console.log(line);
|
|
31
|
+
console.log(c.green(` \u2713 DevFlow v${version} installed successfully!`));
|
|
32
|
+
console.log(line);
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function printUpdateSuccess(version) {
|
|
37
|
+
const line = c.green('\u2501'.repeat(55));
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(line);
|
|
40
|
+
console.log(c.green(` \u2713 DevFlow updated to v${version}!`));
|
|
41
|
+
console.log(line);
|
|
42
|
+
console.log();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Interactive y/N confirmation
|
|
46
|
+
function confirm(question) {
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const rl = readline.createInterface({
|
|
49
|
+
input: process.stdin,
|
|
50
|
+
output: process.stdout,
|
|
51
|
+
});
|
|
52
|
+
rl.question(`${question} (y/N) `, (answer) => {
|
|
53
|
+
rl.close();
|
|
54
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check if a CLI command exists
|
|
60
|
+
function commandExists(cmd) {
|
|
61
|
+
try {
|
|
62
|
+
execSync(`command -v ${cmd}`, { stdio: 'ignore' });
|
|
63
|
+
return true;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Check required/recommended dependencies
|
|
70
|
+
function checkDependencies() {
|
|
71
|
+
const platform = process.platform === 'darwin' ? 'macOS'
|
|
72
|
+
: process.platform === 'win32' ? 'Windows'
|
|
73
|
+
: 'Linux';
|
|
74
|
+
info(`System: ${platform}`);
|
|
75
|
+
console.log();
|
|
76
|
+
|
|
77
|
+
if (commandExists('claude')) {
|
|
78
|
+
success('Claude Code: installed');
|
|
79
|
+
} else {
|
|
80
|
+
warn('Claude Code: not found');
|
|
81
|
+
console.log(' Install: npm install -g @anthropic-ai/claude-code');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (commandExists('git')) {
|
|
85
|
+
success('Git: installed');
|
|
86
|
+
} else {
|
|
87
|
+
warn('Git: not found (recommended)');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Copy directory recursively using Node 18+ fs.cp
|
|
94
|
+
async function copyDir(src, dest) {
|
|
95
|
+
await fs.promises.mkdir(path.dirname(dest), { recursive: true });
|
|
96
|
+
await fs.promises.cp(src, dest, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Copy single file, creating parent dirs as needed
|
|
100
|
+
async function copyFile(src, dest) {
|
|
101
|
+
await fs.promises.mkdir(path.dirname(dest), { recursive: true });
|
|
102
|
+
await fs.promises.copyFile(src, dest);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Create multiple directories
|
|
106
|
+
async function ensureDirs(root, dirs) {
|
|
107
|
+
for (const dir of dirs) {
|
|
108
|
+
await fs.promises.mkdir(path.join(root, dir), { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Create .gitkeep in directories that should be tracked but are empty
|
|
113
|
+
async function createGitkeep(root, dirs) {
|
|
114
|
+
for (const dir of dirs) {
|
|
115
|
+
const gitkeepPath = path.join(root, dir, '.gitkeep');
|
|
116
|
+
try {
|
|
117
|
+
await fs.promises.access(gitkeepPath);
|
|
118
|
+
} catch {
|
|
119
|
+
await fs.promises.writeFile(gitkeepPath, '');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check if a path exists
|
|
125
|
+
async function pathExists(p) {
|
|
126
|
+
try {
|
|
127
|
+
await fs.promises.access(p);
|
|
128
|
+
return true;
|
|
129
|
+
} catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Resolve target path relative to cwd
|
|
135
|
+
function resolveTarget(targetArg) {
|
|
136
|
+
return path.resolve(process.cwd(), targetArg);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
c,
|
|
141
|
+
printHeader,
|
|
142
|
+
success,
|
|
143
|
+
error,
|
|
144
|
+
warn,
|
|
145
|
+
info,
|
|
146
|
+
printSuccess,
|
|
147
|
+
printUpdateSuccess,
|
|
148
|
+
confirm,
|
|
149
|
+
commandExists,
|
|
150
|
+
checkDependencies,
|
|
151
|
+
copyDir,
|
|
152
|
+
copyFile,
|
|
153
|
+
ensureDirs,
|
|
154
|
+
createGitkeep,
|
|
155
|
+
pathExists,
|
|
156
|
+
resolveTarget,
|
|
157
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devflow-agents",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Multi-agent system for software development with Claude Code. 6 specialized agents (Strategist, Architect, System Designer, Builder, Guardian, Chronicler) as slash commands.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"ai-agents",
|
|
8
|
+
"multi-agent",
|
|
9
|
+
"devflow",
|
|
10
|
+
"claude",
|
|
11
|
+
"anthropic",
|
|
12
|
+
"software-development"
|
|
13
|
+
],
|
|
14
|
+
"author": "Evolve Labs",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/evolve-labs-cloud/devflow.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/evolve-labs-cloud/devflow",
|
|
21
|
+
"bin": {
|
|
22
|
+
"devflow": "bin/devflow.js"
|
|
23
|
+
},
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18.0.0"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"bin/",
|
|
30
|
+
"lib/",
|
|
31
|
+
".claude/commands/",
|
|
32
|
+
".claude_project",
|
|
33
|
+
".devflow/agents/",
|
|
34
|
+
".devflow/project.yaml",
|
|
35
|
+
".gitignore-template",
|
|
36
|
+
"docs/decisions/000-template.md",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"commander": "^12.0.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"prepublishOnly": "cp .gitignore .gitignore-template"
|
|
45
|
+
}
|
|
46
|
+
}
|