@jahanxu/code-flow 0.2.0 → 0.2.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/package.json +1 -1
- package/src/cli.js +91 -6
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -6,9 +6,12 @@ const fs = require('fs');
|
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const { spawnSync } = require('child_process');
|
|
8
8
|
|
|
9
|
+
const pkg = require('../package.json');
|
|
10
|
+
|
|
9
11
|
const usage = [
|
|
10
12
|
'Usage: code-flow init',
|
|
11
|
-
' code-flow --
|
|
13
|
+
' code-flow -v | --version',
|
|
14
|
+
' code-flow -h | --help'
|
|
12
15
|
].join('\n');
|
|
13
16
|
|
|
14
17
|
function printUsage(stream) {
|
|
@@ -57,6 +60,21 @@ function copyDirRecursive(srcDir, destDir) {
|
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
function collectFiles(dir, base) {
|
|
64
|
+
const results = [];
|
|
65
|
+
if (!fs.existsSync(dir)) return results;
|
|
66
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
67
|
+
for (const entry of entries) {
|
|
68
|
+
const rel = path.join(base, entry.name);
|
|
69
|
+
if (entry.isDirectory()) {
|
|
70
|
+
results.push(...collectFiles(path.join(dir, entry.name), rel));
|
|
71
|
+
} else if (entry.isFile()) {
|
|
72
|
+
results.push(rel);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
|
|
60
78
|
function runInit() {
|
|
61
79
|
ensurePython3();
|
|
62
80
|
|
|
@@ -65,24 +83,91 @@ function runInit() {
|
|
|
65
83
|
const coreDir = path.join(baseDir, 'core');
|
|
66
84
|
const adaptersDir = path.join(baseDir, 'adapters');
|
|
67
85
|
|
|
86
|
+
const created = [];
|
|
87
|
+
const skipped = [];
|
|
88
|
+
|
|
89
|
+
// Track files before copy
|
|
90
|
+
const track = (srcDir, destDir, prefix) => {
|
|
91
|
+
if (!fs.existsSync(srcDir)) return;
|
|
92
|
+
const files = collectFiles(srcDir, '');
|
|
93
|
+
for (const rel of files) {
|
|
94
|
+
const dest = path.join(destDir, rel);
|
|
95
|
+
const label = path.join(prefix, rel);
|
|
96
|
+
if (fs.existsSync(dest)) {
|
|
97
|
+
skipped.push(label);
|
|
98
|
+
} else {
|
|
99
|
+
created.push(label);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
track(path.join(coreDir, 'code-flow'), path.join(cwd, '.code-flow'), '.code-flow');
|
|
105
|
+
const claudeMdDest = path.join(cwd, 'CLAUDE.md');
|
|
106
|
+
if (fs.existsSync(claudeMdDest)) {
|
|
107
|
+
skipped.push('CLAUDE.md');
|
|
108
|
+
} else {
|
|
109
|
+
created.push('CLAUDE.md');
|
|
110
|
+
}
|
|
111
|
+
track(path.join(adaptersDir, 'claude', 'commands'), path.join(cwd, '.claude', 'commands'), '.claude/commands');
|
|
112
|
+
const settingsDest = path.join(cwd, '.claude', 'settings.local.json');
|
|
113
|
+
if (fs.existsSync(settingsDest)) {
|
|
114
|
+
skipped.push('.claude/settings.local.json');
|
|
115
|
+
} else {
|
|
116
|
+
created.push('.claude/settings.local.json');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Perform copy
|
|
68
120
|
copyDirRecursive(path.join(coreDir, 'code-flow'), path.join(cwd, '.code-flow'));
|
|
69
|
-
copyFileIfMissing(path.join(adaptersDir, 'claude', 'CLAUDE.md'),
|
|
70
|
-
|
|
121
|
+
copyFileIfMissing(path.join(adaptersDir, 'claude', 'CLAUDE.md'), claudeMdDest);
|
|
122
|
+
fs.mkdirSync(path.join(cwd, '.claude', 'commands'), { recursive: true });
|
|
123
|
+
copyDirRecursive(path.join(adaptersDir, 'claude', 'commands'), path.join(cwd, '.claude', 'commands'));
|
|
124
|
+
copyFileIfMissing(path.join(adaptersDir, 'claude', 'settings.local.json'), settingsDest);
|
|
71
125
|
|
|
72
126
|
// Clean up legacy .claude/skills/ if it exists
|
|
73
127
|
const legacySkills = path.join(cwd, '.claude', 'skills');
|
|
74
128
|
if (fs.existsSync(legacySkills)) {
|
|
75
129
|
fs.rmSync(legacySkills, { recursive: true });
|
|
130
|
+
process.stdout.write('Cleaned up legacy .claude/skills/\n');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Install pyyaml
|
|
134
|
+
const pip = spawnSync('python3', ['-m', 'pip', 'install', 'pyyaml'], {
|
|
135
|
+
stdio: 'ignore'
|
|
136
|
+
});
|
|
137
|
+
if (pip.error || pip.status !== 0) {
|
|
138
|
+
process.stderr.write('Warning: pyyaml install failed. Run manually: pip install pyyaml\n');
|
|
76
139
|
}
|
|
77
140
|
|
|
78
|
-
|
|
79
|
-
process.stdout.write('
|
|
141
|
+
// Output summary
|
|
142
|
+
process.stdout.write('\ncode-flow initialized!\n\n');
|
|
143
|
+
if (created.length > 0) {
|
|
144
|
+
process.stdout.write('Created:\n');
|
|
145
|
+
for (const f of created) {
|
|
146
|
+
process.stdout.write(` + ${f}\n`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (skipped.length > 0) {
|
|
150
|
+
process.stdout.write('Skipped (already exist):\n');
|
|
151
|
+
for (const f of skipped) {
|
|
152
|
+
process.stdout.write(` - ${f}\n`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
process.stdout.write('\nNext steps:\n');
|
|
156
|
+
process.stdout.write(' 1. Edit CLAUDE.md — fill in team/project info\n');
|
|
157
|
+
process.stdout.write(' 2. Edit .code-flow/specs/ — fill in your coding standards\n');
|
|
158
|
+
process.stdout.write(' 3. Run /project:cf-learn in Claude Code to auto-discover constraints\n');
|
|
80
159
|
process.exit(0);
|
|
81
160
|
}
|
|
82
161
|
|
|
83
162
|
const args = process.argv.slice(2);
|
|
84
163
|
|
|
85
|
-
if (args.
|
|
164
|
+
if (args.includes('-v') || args.includes('--version')) {
|
|
165
|
+
process.stdout.write(`${pkg.version}\n`);
|
|
166
|
+
process.exit(0);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (args.includes('-h') || args.includes('--help')) {
|
|
170
|
+
process.stdout.write(`code-flow v${pkg.version}\n\n`);
|
|
86
171
|
printUsage(process.stdout);
|
|
87
172
|
process.exit(0);
|
|
88
173
|
}
|