@jahanxu/code-flow 0.1.2 → 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/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 --help'
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,27 +83,91 @@ function runInit() {
65
83
  const coreDir = path.join(baseDir, 'core');
66
84
  const adaptersDir = path.join(baseDir, 'adapters');
67
85
 
68
- copyDirRecursive(path.join(coreDir, 'code-flow'), path.join(cwd, '.code-flow'));
69
- copyFileIfMissing(path.join(adaptersDir, 'claude', 'CLAUDE.md'), path.join(cwd, 'CLAUDE.md'));
70
- copyDirRecursive(path.join(adaptersDir, 'claude'), path.join(cwd, '.claude'));
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
+ }
71
118
 
72
- const result = spawnSync(
73
- 'python3',
74
- ['.code-flow/scripts/cf_init.py'],
75
- { stdio: 'inherit', cwd }
76
- );
119
+ // Perform copy
120
+ copyDirRecursive(path.join(coreDir, 'code-flow'), path.join(cwd, '.code-flow'));
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);
125
+
126
+ // Clean up legacy .claude/skills/ if it exists
127
+ const legacySkills = path.join(cwd, '.claude', 'skills');
128
+ if (fs.existsSync(legacySkills)) {
129
+ fs.rmSync(legacySkills, { recursive: true });
130
+ process.stdout.write('Cleaned up legacy .claude/skills/\n');
131
+ }
77
132
 
78
- if (result.error) {
79
- process.stderr.write(`Error: ${result.error.message}\n`);
80
- process.exit(1);
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');
81
139
  }
82
140
 
83
- process.exit(result.status ?? 0);
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');
159
+ process.exit(0);
84
160
  }
85
161
 
86
162
  const args = process.argv.slice(2);
87
163
 
88
- if (args.length === 1 && args[0] === '--help') {
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`);
89
171
  printUsage(process.stdout);
90
172
  process.exit(0);
91
173
  }
@@ -1,13 +0,0 @@
1
- # cf-init
2
-
3
- 初始化 code-flow 规范体系(目录、配置、spec、skill、hooks)。
4
-
5
- ## Usage
6
- - `/cf-init`
7
- - `/cf-init frontend|backend|fullstack`
8
-
9
- ## Command
10
- - `python3 .code-flow/scripts/cf_init.py [frontend|backend|fullstack]`
11
-
12
- ## Notes
13
- - 依赖 Python 3.9+ 与 pyyaml(脚本会尝试自动安装)。
@@ -1,12 +0,0 @@
1
- # cf-inject
2
-
3
- 手动注入指定领域或文件路径对应的规范(Hook 失败时回退)。
4
-
5
- ## Usage
6
- - `/cf-inject frontend|backend`
7
- - `/cf-inject path/to/file.ext`
8
- - `/cf-inject --list-specs --domain=frontend`
9
-
10
- ## Command
11
- - `python3 .code-flow/scripts/cf_inject.py [domain|file_path]`
12
- - `python3 .code-flow/scripts/cf_inject.py --list-specs --domain=frontend`
@@ -1,11 +0,0 @@
1
- # cf-learn
2
-
3
- 将经验沉淀到对应规范的 Learnings 段落。
4
-
5
- ## Usage
6
- - `/cf-learn --scope=global --content="..." `
7
- - `/cf-learn --scope=frontend --content="..." --file=frontend/component-specs.md`
8
- - `/cf-learn --scope=backend --content="..." --file=backend/logging.md`
9
-
10
- ## Command
11
- - `python3 .code-flow/scripts/cf_learn.py --scope=global|frontend|backend --content=\"...\" [--file=spec] [--dry-run]`
@@ -1,12 +0,0 @@
1
- # cf-scan
2
-
3
- 审计规范文件的 token 分布与问题提示。
4
-
5
- ## Usage
6
- - `/cf-scan`
7
- - `/cf-scan --json`
8
- - `/cf-scan --only-issues`
9
- - `/cf-scan --limit=10`
10
-
11
- ## Command
12
- - `python3 .code-flow/scripts/cf_scan.py [--json] [--only-issues] [--limit=N]`
@@ -1,11 +0,0 @@
1
- # cf-stats
2
-
3
- 统计 L0/L1 规范 token 使用情况。
4
-
5
- ## Usage
6
- - `/cf-stats`
7
- - `/cf-stats --human`
8
- - `/cf-stats --domain=frontend`
9
-
10
- ## Command
11
- - `python3 .code-flow/scripts/cf_stats.py [--human] [--domain=frontend]`
@@ -1,12 +0,0 @@
1
- # cf-validate
2
-
3
- 基于变更文件执行验证规则(类型检查/测试/lint)。
4
-
5
- ## Usage
6
- - `/cf-validate`
7
- - `/cf-validate path/to/file.py`
8
- - `/cf-validate --files=src/a.ts,src/b.ts`
9
- - `/cf-validate --only-failed`
10
-
11
- ## Command
12
- - `python3 .code-flow/scripts/cf_validate.py [file_path] [--files=...] [--only-failed] [--json-short] [--output=table]`