6a-spec-install 1.0.1-dev.1 → 1.0.1-dev.2

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/README.md CHANGED
@@ -7,19 +7,32 @@
7
7
  ### 安装
8
8
 
9
9
  ```bash
10
- # 安装 Cursor 配置(默认)
10
+ # 安装 Cursor 配置(默认,完全覆盖模式)
11
11
  npx 6a-spec-install
12
12
 
13
- # 安装 Cursor 配置
14
- npx 6a-spec-install --tool cursor
13
+ # 智能合并模式(推荐,保留用户自定义文件)
14
+ npx 6a-spec-install --tool cursor --merge
15
15
 
16
- # 安装 Claude 配置
17
- npx 6a-spec-install --tool claude
16
+ # 安装 Claude 配置(合并模式)
17
+ npx 6a-spec-install --tool claude --merge
18
18
 
19
19
  # 同时安装两种工具
20
- npx 6a-spec-install --tool all
20
+ npx 6a-spec-install --tool all --merge
21
21
  ```
22
22
 
23
+ ### 安装模式
24
+
25
+ #### 完全覆盖模式(默认)
26
+ - 会先备份现有配置到 `.cursor.backup.时间戳`
27
+ - 完全覆盖目标目录
28
+ - 适合首次安装或需要完全重置配置
29
+
30
+ #### 智能合并模式(`--merge`)
31
+ - **只更新包中存在的文件**,保留用户新增的自定义文件
32
+ - 不会创建备份(因为不会删除文件)
33
+ - 适合更新配置时保留自定义修改
34
+ - 会显示更新和新增的文件统计
35
+
23
36
  ### 全局安装(可选)
24
37
 
25
38
  ```bash
@@ -33,7 +46,8 @@ npm install -g 6a-spec-install
33
46
 
34
47
  - ✅ 支持 Cursor IDE
35
48
  - ✅ 支持 Claude Desktop
36
- - ✅ 自动备份现有配置
49
+ - ✅ 智能合并模式:保留用户自定义文件,只更新包中文件
50
+ - ✅ 完全覆盖模式:自动备份现有配置后完全覆盖
37
51
  - ✅ 一键安装,开箱即用
38
52
 
39
53
  ## 目录结构
@@ -52,10 +66,18 @@ npm install -g 6a-spec-install
52
66
  ## 更新
53
67
 
54
68
  ```bash
55
- # 更新到最新版本
69
+ # 更新到最新版本(智能合并,推荐)
70
+ npx 6a-spec-install@latest --tool cursor --merge
71
+
72
+ # 更新到最新版本(完全覆盖)
56
73
  npx 6a-spec-install@latest --tool cursor
57
74
  ```
58
75
 
76
+ **推荐使用 `--merge` 模式**,这样可以:
77
+ - 保留你在 `.cursor/` 目录中自定义的文件
78
+ - 只更新包中提供的文件
79
+ - 不会丢失你的个性化配置
80
+
59
81
  ## 开发
60
82
 
61
83
  ### 本地测试
@@ -7,6 +7,7 @@ const installer = require('../lib/installer');
7
7
  const args = process.argv.slice(2);
8
8
  let tool = 'cursor';
9
9
  let help = false;
10
+ let mergeMode = false;
10
11
 
11
12
  for (let i = 0; i < args.length; i++) {
12
13
  const arg = args[i];
@@ -14,6 +15,8 @@ for (let i = 0; i < args.length; i++) {
14
15
  tool = args[++i] || 'cursor';
15
16
  } else if (arg === '--help' || arg === '-h') {
16
17
  help = true;
18
+ } else if (arg === '--merge' || arg === '-m') {
19
+ mergeMode = true;
17
20
  }
18
21
  }
19
22
 
@@ -26,13 +29,14 @@ if (help) {
26
29
 
27
30
  选项:
28
31
  --tool, -t TOOL 安装目标工具 (cursor/claude/all, 默认: cursor)
32
+ --merge, -m 智能合并模式(保留用户自定义文件,只更新包中文件)
29
33
  --help, -h 显示帮助信息
30
34
 
31
35
  示例:
32
- npx 6a-spec-install --tool cursor # 只安装 Cursor 配置
33
- npx 6a-spec-install --tool claude # 只安装 Claude 配置
34
- npx 6a-spec-install --tool all # 安装两种工具配置
35
- npx 6a-spec-install # 默认安装 Cursor 配置
36
+ npx 6a-spec-install --tool cursor # 完全覆盖模式(会先备份)
37
+ npx 6a-spec-install --tool cursor --merge # 智能合并模式(保留自定义文件)
38
+ npx 6a-spec-install --tool claude --merge # 安装 Claude 配置(合并模式)
39
+ npx 6a-spec-install --tool all # 安装两种工具配置
36
40
 
37
41
  支持的工具:
38
42
  cursor - 安装 Cursor IDE 的提示词配置
@@ -43,7 +47,7 @@ if (help) {
43
47
  }
44
48
 
45
49
  // 执行安装
46
- installer.install(tool).catch(err => {
50
+ installer.install(tool, mergeMode).catch(err => {
47
51
  console.error('❌ 安装失败:', err.message);
48
52
  process.exit(1);
49
53
  });
package/lib/installer.js CHANGED
@@ -6,6 +6,7 @@ class Installer {
6
6
  // 获取包目录(安装后)
7
7
  this.packageDir = this.findPackageDir();
8
8
  this.targetDir = process.cwd();
9
+ this.mergeMode = false; // 合并模式标志
9
10
  }
10
11
 
11
12
  // 查找包目录(支持本地开发和 npm 安装)
@@ -50,7 +51,7 @@ class Installer {
50
51
  return null;
51
52
  }
52
53
 
53
- // 递归复制目录
54
+ // 递归复制目录(完全覆盖模式)
54
55
  copyDir(src, dest) {
55
56
  if (!fs.existsSync(dest)) {
56
57
  fs.mkdirSync(dest, { recursive: true });
@@ -70,6 +71,60 @@ class Installer {
70
71
  }
71
72
  }
72
73
 
74
+ // 智能合并目录(只更新包中存在的文件,保留用户自定义文件)
75
+ mergeDir(src, dest) {
76
+ if (!fs.existsSync(dest)) {
77
+ fs.mkdirSync(dest, { recursive: true });
78
+ }
79
+
80
+ const entries = fs.readdirSync(src, { withFileTypes: true });
81
+ let updatedCount = 0;
82
+ let addedCount = 0;
83
+
84
+ for (const entry of entries) {
85
+ const srcPath = path.join(src, entry.name);
86
+ const destPath = path.join(dest, entry.name);
87
+
88
+ if (entry.isDirectory()) {
89
+ const result = this.mergeDir(srcPath, destPath);
90
+ updatedCount += result.updated;
91
+ addedCount += result.added;
92
+ } else {
93
+ const exists = fs.existsSync(destPath);
94
+ fs.copyFileSync(srcPath, destPath);
95
+ if (exists) {
96
+ updatedCount++;
97
+ } else {
98
+ addedCount++;
99
+ }
100
+ }
101
+ }
102
+
103
+ return { updated: updatedCount, added: addedCount };
104
+ }
105
+
106
+ // 获取目录中所有文件的相对路径列表
107
+ getAllFiles(dir, baseDir = dir) {
108
+ const files = [];
109
+ if (!fs.existsSync(dir)) {
110
+ return files;
111
+ }
112
+
113
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
114
+ for (const entry of entries) {
115
+ const fullPath = path.join(dir, entry.name);
116
+ const relativePath = path.relative(baseDir, fullPath);
117
+
118
+ if (entry.isDirectory()) {
119
+ files.push(...this.getAllFiles(fullPath, baseDir));
120
+ } else {
121
+ files.push(relativePath);
122
+ }
123
+ }
124
+
125
+ return files;
126
+ }
127
+
73
128
  // 安装 Cursor 配置
74
129
  installCursor() {
75
130
  this.log('开始安装 Cursor 配置...');
@@ -81,10 +136,35 @@ class Installer {
81
136
  throw new Error('未找到 .cursor 源目录');
82
137
  }
83
138
 
84
- this.backupDir(targetDir);
139
+ const targetExists = fs.existsSync(targetDir);
85
140
 
86
- this.log('复制 Cursor 配置文件...');
87
- this.copyDir(sourceDir, targetDir);
141
+ if (this.mergeMode && targetExists) {
142
+ // 智能合并模式
143
+ this.log('使用智能合并模式(保留用户自定义文件)...');
144
+
145
+ // 统计用户自定义文件
146
+ const sourceFiles = new Set(this.getAllFiles(sourceDir, sourceDir));
147
+ const targetFiles = this.getAllFiles(targetDir, targetDir);
148
+ const customFiles = targetFiles.filter(f => !sourceFiles.has(f));
149
+
150
+ if (customFiles.length > 0) {
151
+ this.log(`检测到 ${customFiles.length} 个用户自定义文件,将保留`, 'info');
152
+ }
153
+
154
+ const result = this.mergeDir(sourceDir, targetDir);
155
+ this.log(`更新了 ${result.updated} 个文件,新增了 ${result.added} 个文件`, 'info');
156
+
157
+ if (customFiles.length > 0) {
158
+ this.log(`保留了 ${customFiles.length} 个用户自定义文件`, 'info');
159
+ }
160
+ } else {
161
+ // 完全覆盖模式
162
+ if (targetExists) {
163
+ this.backupDir(targetDir);
164
+ }
165
+ this.log('复制 Cursor 配置文件...');
166
+ this.copyDir(sourceDir, targetDir);
167
+ }
88
168
 
89
169
  this.log('✓ Cursor 配置安装完成!', 'success');
90
170
  }
@@ -100,44 +180,90 @@ class Installer {
100
180
  throw new Error('未找到源配置目录');
101
181
  }
102
182
 
103
- this.backupDir(targetDir);
104
-
105
- this.log('转换并复制 Claude 配置文件...');
183
+ const targetExists = fs.existsSync(targetDir);
106
184
 
107
185
  // 创建目标目录结构
108
186
  if (!fs.existsSync(targetDir)) {
109
187
  fs.mkdirSync(targetDir, { recursive: true });
110
188
  }
111
189
 
112
- // 复制 commands prompts
113
- const commandsDir = path.join(sourceDir, 'commands');
114
- if (fs.existsSync(commandsDir)) {
115
- const promptsDir = path.join(targetDir, 'prompts');
116
- this.copyDir(commandsDir, promptsDir);
117
- }
190
+ if (this.mergeMode && targetExists) {
191
+ // 智能合并模式
192
+ this.log('使用智能合并模式(保留用户自定义文件)...');
193
+
194
+ // 复制 commands 到 prompts
195
+ const commandsDir = path.join(sourceDir, 'commands');
196
+ if (fs.existsSync(commandsDir)) {
197
+ const promptsDir = path.join(targetDir, 'prompts');
198
+ const result = this.mergeDir(commandsDir, promptsDir);
199
+ if (result.updated > 0 || result.added > 0) {
200
+ this.log(`prompts: 更新了 ${result.updated} 个文件,新增了 ${result.added} 个文件`, 'info');
201
+ }
202
+ }
118
203
 
119
- // 复制 rules
120
- const rulesDir = path.join(sourceDir, 'rules');
121
- if (fs.existsSync(rulesDir)) {
122
- const targetRulesDir = path.join(targetDir, 'rules');
123
- this.copyDir(rulesDir, targetRulesDir);
124
- }
204
+ // 复制 rules
205
+ const rulesDir = path.join(sourceDir, 'rules');
206
+ if (fs.existsSync(rulesDir)) {
207
+ const targetRulesDir = path.join(targetDir, 'rules');
208
+ const result = this.mergeDir(rulesDir, targetRulesDir);
209
+ if (result.updated > 0 || result.added > 0) {
210
+ this.log(`rules: 更新了 ${result.updated} 个文件,新增了 ${result.added} 个文件`, 'info');
211
+ }
212
+ }
213
+
214
+ // 复制 scripts
215
+ const scriptDir = path.join(sourceDir, 'script');
216
+ if (fs.existsSync(scriptDir)) {
217
+ const targetScriptDir = path.join(targetDir, 'script');
218
+ const result = this.mergeDir(scriptDir, targetScriptDir);
219
+ if (result.updated > 0 || result.added > 0) {
220
+ this.log(`script: 更新了 ${result.updated} 个文件,新增了 ${result.added} 个文件`, 'info');
221
+ }
222
+ }
223
+ } else {
224
+ // 完全覆盖模式
225
+ if (targetExists) {
226
+ this.backupDir(targetDir);
227
+ }
228
+ this.log('转换并复制 Claude 配置文件...');
229
+
230
+ // 复制 commands 到 prompts
231
+ const commandsDir = path.join(sourceDir, 'commands');
232
+ if (fs.existsSync(commandsDir)) {
233
+ const promptsDir = path.join(targetDir, 'prompts');
234
+ this.copyDir(commandsDir, promptsDir);
235
+ }
125
236
 
126
- // 复制 scripts
127
- const scriptDir = path.join(sourceDir, 'script');
128
- if (fs.existsSync(scriptDir)) {
129
- const targetScriptDir = path.join(targetDir, 'script');
130
- this.copyDir(scriptDir, targetScriptDir);
237
+ // 复制 rules
238
+ const rulesDir = path.join(sourceDir, 'rules');
239
+ if (fs.existsSync(rulesDir)) {
240
+ const targetRulesDir = path.join(targetDir, 'rules');
241
+ this.copyDir(rulesDir, targetRulesDir);
242
+ }
243
+
244
+ // 复制 scripts
245
+ const scriptDir = path.join(sourceDir, 'script');
246
+ if (fs.existsSync(scriptDir)) {
247
+ const targetScriptDir = path.join(targetDir, 'script');
248
+ this.copyDir(scriptDir, targetScriptDir);
249
+ }
131
250
  }
132
251
 
133
252
  this.log('✓ Claude 配置安装完成!', 'success');
134
253
  }
135
254
 
136
255
  // 主安装方法
137
- async install(tool = 'cursor') {
256
+ async install(tool = 'cursor', mergeMode = false) {
257
+ this.mergeMode = mergeMode;
258
+
138
259
  this.log(`6A-spec 安装工具`);
139
260
  this.log(`目标目录: ${this.targetDir}`);
140
261
  this.log(`工具: ${tool}`);
262
+ if (mergeMode) {
263
+ this.log(`模式: 智能合并(保留用户自定义文件)`, 'info');
264
+ } else {
265
+ this.log(`模式: 完全覆盖(会先备份现有配置)`, 'info');
266
+ }
141
267
 
142
268
  try {
143
269
  switch (tool.toLowerCase()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "6a-spec-install",
3
- "version": "1.0.1-dev.1",
3
+ "version": "1.0.1-dev.2",
4
4
  "description": "6A-spec 驱动开发提示词安装工具,支持 Cursor 和 Claude",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {