clawt 1.0.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.
Files changed (43) hide show
  1. package/.claude/agent-memory/docs-sync-updater/MEMORY.md +48 -0
  2. package/.claude/agents/docs-sync-updater.md +128 -0
  3. package/CLAUDE.md +71 -0
  4. package/README.md +168 -0
  5. package/dist/index.js +923 -0
  6. package/dist/postinstall.js +71 -0
  7. package/docs/spec.md +710 -0
  8. package/package.json +38 -0
  9. package/scripts/postinstall.ts +116 -0
  10. package/src/commands/create.ts +49 -0
  11. package/src/commands/list.ts +45 -0
  12. package/src/commands/merge.ts +142 -0
  13. package/src/commands/remove.ts +127 -0
  14. package/src/commands/run.ts +310 -0
  15. package/src/commands/validate.ts +137 -0
  16. package/src/constants/branch.ts +6 -0
  17. package/src/constants/config.ts +8 -0
  18. package/src/constants/exitCodes.ts +9 -0
  19. package/src/constants/index.ts +6 -0
  20. package/src/constants/messages.ts +61 -0
  21. package/src/constants/paths.ts +14 -0
  22. package/src/constants/terminal.ts +13 -0
  23. package/src/errors/index.ts +20 -0
  24. package/src/index.ts +55 -0
  25. package/src/logger/index.ts +34 -0
  26. package/src/types/claudeCode.ts +14 -0
  27. package/src/types/command.ts +39 -0
  28. package/src/types/config.ts +7 -0
  29. package/src/types/index.ts +5 -0
  30. package/src/types/taskResult.ts +31 -0
  31. package/src/types/worktree.ts +7 -0
  32. package/src/utils/branch.ts +51 -0
  33. package/src/utils/config.ts +35 -0
  34. package/src/utils/formatter.ts +67 -0
  35. package/src/utils/fs.ts +28 -0
  36. package/src/utils/git.ts +243 -0
  37. package/src/utils/index.ts +35 -0
  38. package/src/utils/prompt.ts +18 -0
  39. package/src/utils/shell.ts +53 -0
  40. package/src/utils/validation.ts +48 -0
  41. package/src/utils/worktree.ts +107 -0
  42. package/tsconfig.json +17 -0
  43. package/tsup.config.ts +25 -0
package/docs/spec.md ADDED
@@ -0,0 +1,710 @@
1
+ # Clawt - Software Specification
2
+
3
+
4
+ > 一个深度融合 Git Worktree 与 Claude Code CLI 的命令行工具,基于本地 Git 项目创建多个隔离的 worktree 环境,并行执行多个 Claude Code Agent 任务,所有 Agent 的代码修改互不干扰。
5
+
6
+ ---
7
+
8
+ ## 目录
9
+
10
+ - [1. 技术栈](#1-技术栈)
11
+ - [2. 核心概念](#2-核心概念)
12
+ - [3. 全局目录结构](#3-全局目录结构)
13
+ - [4. 命令总览](#4-命令总览)
14
+ - [5. 需求场景详细设计](#5-需求场景详细设计)
15
+ - [5.1 批量创建 Worktree](#51-批量创建-worktreeworktree-对应分支)
16
+ - [5.2 批量创建 Worktree + 执行 Claude Code 任务](#52-批量创建-worktree--执行-claude-code-任务)
17
+ - [5.3 任务完成通知机制](#53-任务完成通知机制)
18
+ - [5.4 在主 Worktree 验证其他分支](#54-在主-worktree-验证其他分支)
19
+ - [5.5 移除 Worktree](#55-移除-worktree)
20
+ - [5.6 合并验证过的分支](#56-合并验证过的分支)
21
+ - [5.7 默认配置文件](#57-默认配置文件)
22
+ - [5.8 获取当前项目所有 Worktree](#58-获取当前项目所有-worktree)
23
+ - [5.9 日志系统](#59-日志系统)
24
+ - [6. 错误处理规范](#6-错误处理规范)
25
+ - [7. 非功能性需求](#7-非功能性需求)
26
+
27
+ ---
28
+
29
+ ## 1. 技术栈
30
+
31
+ | 类别 | 选型 |
32
+ | -------- | ----------------------------- |
33
+ | 运行时 | Node.js >= 18 |
34
+ | 语言 | TypeScript |
35
+ | 包管理 | npm |
36
+ | CLI 框架 | Commander.js |
37
+ | 日志库 | winston (按日期滚动文件) |
38
+ | 交互式 | enquirer (选项选择/确认对话) |
39
+ | 构建 | tsup / tsc |
40
+ | 分发 | npm 全局安装 (`npm i -g clawt`) |
41
+
42
+ ---
43
+
44
+ ## 2. 核心概念
45
+
46
+ ### 2.1 "主 Worktree" 的定义与定位规则
47
+
48
+ **主 worktree** = `git rev-parse --git-common-dir` 所在的原始 worktree。
49
+
50
+ **强制约束:**
51
+
52
+ - `clawt` 命令 **只能** 在主 worktree 的仓库**根目录**执行。
53
+ - 校验条件:`git rev-parse --git-common-dir === ".git"`
54
+ - 如果不等于 `.git`(例如返回了绝对路径如 `/xxx/.git`),说明当前目录是子 worktree 或子目录,必须拒绝执行并提示用户。
55
+ - 还需校验当前目录是否为仓库根目录(存在 `.git` 目录)。
56
+
57
+ **校验伪代码:**
58
+
59
+ ```typescript
60
+ const gitCommonDir = execSync('git rev-parse --git-common-dir').toString().trim();
61
+ if (gitCommonDir !== '.git') {
62
+ // 报错:请在主 worktree 的根目录下执行 clawt
63
+ process.exit(1);
64
+ }
65
+ ```
66
+
67
+ ### 2.2 项目名获取
68
+
69
+ ```bash
70
+ project=$(basename "$(git rev-parse --show-toplevel)")
71
+ ```
72
+
73
+ 等价 TypeScript:
74
+
75
+ ```typescript
76
+ const projectRoot = execSync('git rev-parse --show-toplevel').toString().trim();
77
+ const projectName = path.basename(projectRoot);
78
+ ```
79
+
80
+ ### 2.3 分支名合法性校验与转换
81
+
82
+ 用户提供的 `branchName` 需要校验,凡是会影响文件系统路径 `~/.clawt/worktrees/<project>/<branchName>` 的非法字符,一律替换为 `-`。
83
+
84
+ **非法字符列表(至少包含):**
85
+
86
+ | 字符 | 说明 |
87
+ | ------- | ------------------------------ |
88
+ | `/` | 路径分隔符 |
89
+ | `\` | 路径分隔符(Windows) |
90
+ | `.` | 可能导致隐藏目录 |
91
+ | `..` | 目录遍历 |
92
+ | ` ` | 空格 |
93
+ | `~` | Home 目录展开 |
94
+ | `:` | Windows 驱动器号 / 特殊用途 |
95
+ | `*` | 通配符 |
96
+ | `?` | 通配符 |
97
+ | `[` `]` | 通配符 |
98
+ | `^` | Git ref 特殊字符 |
99
+
100
+ **转换规则:**
101
+
102
+ 1. 将所有非法字符替换为 `-`
103
+ 2. 将连续的 `-` 压缩为一个 `-`
104
+ 3. 去除首尾 `-`
105
+
106
+ **示例输出:**
107
+
108
+ ```
109
+ 原始分支名: feature/a.b
110
+ 实际使用分支名: feature-a-b
111
+ ```
112
+
113
+ 如果发生了转换,**必须**在终端输出提示告知用户。
114
+
115
+ ### 2.4 分支名存在性校验
116
+
117
+ 创建前先检验分支名是否已经存在:
118
+
119
+ ```bash
120
+ git show-ref --verify refs/heads/<branchName> 2>/dev/null
121
+ ```
122
+
123
+ - 有输出 → 分支已存在 → 报错并退出
124
+ - 无输出 → 分支不存在 → 可以继续
125
+
126
+ > 注意:当 `n > 1` 时,需要校验的是 `branchName-1`、`branchName-2`、……、`branchName-n` 这些分支名。只要有一个已存在,就报错并退出(在创建任何 worktree 之前完成全部校验)。
127
+
128
+ ---
129
+
130
+ ## 3. 全局目录结构
131
+
132
+ ```
133
+ ~/.clawt/
134
+ ├── config.json # 全局配置文件
135
+ ├── logs/ # 日志目录
136
+ │ ├── clawt-2025-02-06.log
137
+ │ └── ...
138
+ └── worktrees/ # 所有 worktree 的统一存放目录
139
+ └── <project-name>/ # 以项目名分组
140
+ ├── <branchName>/ # n=1 时直接使用分支名
141
+ ├── <branchName>-1/ # n>1 时使用后缀编号
142
+ ├── <branchName>-2/
143
+ └── ...
144
+ ```
145
+
146
+ **注意:** 不需要支持多个不同路径下同名 repo 的区分。如果两个不同目录都叫 `main-project`,不做处理(视为同一个项目)。
147
+
148
+ ---
149
+
150
+ ## 4. 命令总览
151
+
152
+ | 命令 | 说明 | 对应场景 |
153
+ | --------------------- | ---------------------------------------------- | -------- |
154
+ | `clawt create` | 批量创建 worktree 及对应分支 | 5.1 |
155
+ | `clawt run` | 批量创建 worktree + 启动 Claude Code 执行任务 | 5.2 |
156
+ | `clawt validate` | 在主 worktree 验证某个 worktree 分支的变更 | 5.4 |
157
+ | `clawt merge` | 合并某个已验证的 worktree 分支到主 worktree | 5.6 |
158
+ | `clawt remove` | 移除 worktree(支持单个/批量/全部) | 5.5 |
159
+ | `clawt list` | 列出当前项目所有 worktree | 5.8 |
160
+
161
+ 所有命令执行前,都必须先执行**主 worktree 校验**(见 [2.1](#21-主-worktree-的定义与定位规则))。
162
+
163
+ ---
164
+
165
+ ## 5. 需求场景详细设计
166
+
167
+ ### 5.1 批量创建 Worktree(Worktree 对应分支)
168
+
169
+ **命令:**
170
+
171
+ ```bash
172
+ clawt create -b <branchName> [-n <count>]
173
+ ```
174
+
175
+ **参数:**
176
+
177
+ | 参数 | 必填 | 说明 |
178
+ | ---- | ---- | ----------------------------------------------------- |
179
+ | `-b` | 是 | 分支名 |
180
+ | `-n` | 否 | 需要创建的 worktree 数量,默认 `1` |
181
+
182
+ **运行流程:**
183
+
184
+ 1. **主 worktree 校验** (2.1)
185
+ 2. **获取项目名** (2.2)
186
+ 3. **分支名合法性校验与转换** (2.3)
187
+ 4. **分支名存在性校验** (2.4)
188
+ - 若 `n = 1`:校验 `branchName`
189
+ - 若 `n > 1`:校验 `branchName-1` 到 `branchName-n`
190
+ - 所有分支名在创建任何 worktree **之前**完成全部校验
191
+ 5. **批量创建 worktree**
192
+ - 若 `n = 1`:
193
+ ```bash
194
+ git worktree add -b <branchName> ~/.clawt/worktrees/<project>/<branchName>
195
+ ```
196
+ - 若 `n > 1`:
197
+ ```bash
198
+ git worktree add -b <branchName>-1 ~/.clawt/worktrees/<project>/<branchName>-1
199
+ git worktree add -b <branchName>-2 ~/.clawt/worktrees/<project>/<branchName>-2
200
+ ...
201
+ git worktree add -b <branchName>-n ~/.clawt/worktrees/<project>/<branchName>-n
202
+ ```
203
+ 6. **输出创建日志**
204
+
205
+ **输出格式:**
206
+
207
+ ```
208
+ ✓ 已创建 3 个 worktree
209
+
210
+ 目录路径1:
211
+ ~/.clawt/worktrees/main-project/feature-scheme-1
212
+ 分支名: feature-scheme-1
213
+ ────────────────────────────────────────
214
+ 目录路径2:
215
+ ~/.clawt/worktrees/main-project/feature-scheme-2
216
+ 分支名: feature-scheme-2
217
+ ────────────────────────────────────────
218
+ 目录路径3:
219
+ ~/.clawt/worktrees/main-project/feature-scheme-3
220
+ 分支名: feature-scheme-3
221
+ ────────────────────────────────────────
222
+ ```
223
+
224
+ ---
225
+
226
+ ### 5.2 批量创建 Worktree + 执行 Claude Code 任务
227
+
228
+ **命令:**
229
+
230
+ ```bash
231
+ # 方式一:通过 --tasks 参数直接指定任务(多任务并行)
232
+ clawt run -b <branchName> --tasks <task1> --tasks <task2> --tasks <task3>
233
+
234
+ # 方式二:不传 --tasks,在 worktree 中打开 Claude Code 交互式界面
235
+ clawt run -b <branchName>
236
+ ```
237
+
238
+ **参数:**
239
+
240
+ | 参数 | 必填 | 说明 |
241
+ | --------- | ---- | ----------------------------------------------------------- |
242
+ | `-b` | 是 | 分支名 |
243
+ | `--tasks` | 否 | 任务描述(可多次指定,每个 --tasks 对应一个任务,任务数量即 worktree 数量)。不传则在 worktree 中打开 Claude Code 交互式界面 |
244
+
245
+ **交互式 Claude Code 界面模式:**
246
+
247
+ 当不传 `--tasks` 时,会创建单个 worktree,然后通过 `spawnSync` + `inherit stdio` 在该 worktree 中直接启动 Claude Code CLI 交互式界面,让用户与 Claude Code 直接交互。
248
+
249
+ 启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,支持自定义命令及参数。
250
+
251
+ **运行流程:**
252
+
253
+ 1. 若传了 `--tasks`,解析得到任务数组 `tasks[]`;若未传,创建单个 worktree 并启动 Claude Code 交互式界面(流程结束,不进入后续并行执行阶段)
254
+ 2. `n = tasks.length`
255
+ 3. 按照 **5.1** 的流程创建 `n` 个 worktree
256
+ 4. 对每个 worktree 并行启动 Claude Code CLI:
257
+ ```bash
258
+ cd ~/.clawt/worktrees/<project>/<branchName>-<i>
259
+ claude -p "<tasks[i]>" --output-format json --permission-mode bypassPermissions
260
+ ```
261
+ 5. 进入**事件监听通知**阶段(见 [5.3](#53-任务完成通知机制))
262
+ 6. **中断处理(Ctrl+C / SIGINT)**
263
+ - 监听 `SIGINT` 信号,用户按下 Ctrl+C 时触发
264
+ - 向所有正在运行的 Claude Code 子进程发送 `SIGTERM` 终止信号
265
+ - 等待所有子进程退出后,进入清理流程:
266
+ - 如果 `autoDeleteBranch` 为 `true`:自动清理本次创建的所有 worktree 和对应分支
267
+ - 否则:交互式询问用户是否移除刚刚创建的 worktree 和对应分支
268
+ - 用户选择保留时,提示可使用 `clawt remove` 手动清理
269
+ - 清理完成后以退出码 `1` 退出
270
+
271
+ **注意:** 当 `n = 1` 时(只有一个任务),worktree 目录命名规则同 **5.1**(不加 `-1` 后缀)。
272
+
273
+ ---
274
+
275
+ ### 5.3 任务完成通知机制
276
+
277
+ **触发条件:** 通过 `clawt run` 启动了多个 Claude Code 任务后自动进入通知模式。
278
+
279
+ **机制说明:**
280
+
281
+ Claude Code CLI 以 `--output-format json` 运行时,退出后会在 stdout 输出如下 JSON:
282
+
283
+ ```json
284
+ {
285
+ "type": "result",
286
+ "subtype": "success",
287
+ "is_error": false,
288
+ "duration_ms": 182809,
289
+ "duration_api_ms": 0,
290
+ "num_turns": 1,
291
+ "result": "xxx",
292
+ "stop_reason": "stop_sequence",
293
+ "session_id": "e771e449-b695-48e7-8006-bbf3f0dd3e98",
294
+ "total_cost_usd": 0,
295
+ "usage": { ... }
296
+ }
297
+ ```
298
+
299
+ **事件监听与通知流程:**
300
+
301
+ 1. 为每个 Claude Code 子进程维护状态(运行中 / 已完成 / 已失败)
302
+ 2. 监听每个子进程的 `close` 事件(基于 Node.js `ChildProcess` 的事件驱动机制)
303
+ 3. 当某个子进程触发 `close` 事件时,解析其 stdout 输出的 JSON
304
+ 4. 在主 worktree 的 clawt 终端实时输出通知:
305
+
306
+ ```
307
+ ✓ [完成] worktree: ~/.clawt/worktrees/main-project/feature-scheme-1
308
+ 分支: feature-scheme-1
309
+ 耗时: 182.8s
310
+ 花费: $0.05
311
+ 结果: success
312
+ ────────────────────────────────────────
313
+ ```
314
+
315
+ 5. 先完成的先通知,**不需要**失败重试机制
316
+ 6. 当所有任务完成后,输出汇总信息:
317
+
318
+ ```
319
+ ════════════════════════════════════════
320
+ 全部任务已完成 (3/3)
321
+ 成功: 2
322
+ 失败: 1
323
+ 总耗时: 245.3s
324
+ 总花费: $0.15
325
+ ════════════════════════════════════════
326
+ ```
327
+
328
+ ---
329
+
330
+ ### 5.4 在主 Worktree 验证其他分支
331
+
332
+ **命令:**
333
+
334
+ ```bash
335
+ clawt validate -b <branchName>
336
+ ```
337
+
338
+ **参数:**
339
+
340
+ | 参数 | 必填 | 说明 |
341
+ | ---- | ---- | ------------------------------------------------------------------------ |
342
+ | `-b` | 是 | 要验证的 worktree 分支名(例如 `feature-scheme-1`) |
343
+
344
+ > **限制:** 单次只能验证一个分支,不支持批量验证。
345
+
346
+ **背景说明:**
347
+
348
+ Git worktree 不会包含 `node_modules`、`.venv` 等依赖文件,每次安装依赖耗时较长。利用 `git stash` 可以在所有 worktree 间共享的特性,将目标 worktree 的变更迁移到主 worktree 进行测试,无需重新安装依赖。
349
+
350
+ **运行流程:**
351
+
352
+ #### 步骤 1:检测主 worktree 工作区状态
353
+
354
+ 执行 `git status --porcelain`,判断主 worktree 是否有未提交的更改。
355
+
356
+ - **无更改** → 进入步骤 2
357
+ - **有更改** → 提示用户选择处理方式,使用交互式选择(方向键切换,回车确认):
358
+
359
+ ```
360
+ ⚠ 主 worktree 当前分支有未提交的更改,请选择处理方式:
361
+
362
+ ❯ reset (推荐) - 丢弃所有更改 (git reset --hard HEAD && git clean -fd)
363
+ stash - 暂存更改 (git add . && git stash)
364
+ exit - 退出,手动处理
365
+ ```
366
+
367
+ | 选项 | 执行命令 | 默认 |
368
+ | ------- | ----------------------------------------- | ---- |
369
+ | `reset` | `git reset --hard HEAD && git clean -fd` | 是 |
370
+ | `stash` | `git add . && git stash` | 否 |
371
+ | `exit` | 退出程序 | 否 |
372
+
373
+ 执行完毕后,通过 `git status --porcelain` 再次检测状态,确保工作区干净。如果仍然不干净,报错退出。
374
+
375
+ #### 步骤 2:在目标 worktree 中创建 stash
376
+
377
+ ```bash
378
+ # 定位目标 worktree
379
+ cd ~/.clawt/worktrees/<project>/<branchName>
380
+
381
+ # 校验目标 worktree 是否有更改
382
+ git status --porcelain
383
+ ```
384
+
385
+ - **无更改** → 输出提示 `该 worktree 的分支上没有任何更改,无需验证`,退出
386
+ - **有更改** → 继续
387
+
388
+ ```bash
389
+ git add .
390
+ git stash push -m "clawt:validate:<branchName>"
391
+ git stash apply
392
+ git restore --staged .
393
+ ```
394
+
395
+ > 此步骤结束后,目标 worktree 的代码保持原样(变更仍然存在于工作区),同时变更已被记录到共享的 stash 中。
396
+
397
+ #### 步骤 3:在主 worktree 应用 stash
398
+
399
+ ```bash
400
+ # 回到主 worktree
401
+ cd <主 worktree 路径>
402
+
403
+ # 校验 stash@{0} 是否为我们创建的
404
+ git stash list
405
+ ```
406
+
407
+ 检查 `stash@{0}` 的消息是否包含 `clawt:validate:<branchName>`:
408
+
409
+ - **不包含** → 报错:`git stash list 已变更,请重新执行`,退出
410
+ - **包含** → 继续
411
+
412
+ ```bash
413
+ git stash pop stash@{0}
414
+ ```
415
+
416
+ #### 步骤 4:输出成功提示
417
+
418
+ ```
419
+ ✓ 已将分支 feature-scheme-1 的变更应用到主 worktree
420
+ 可以开始验证了
421
+ ```
422
+
423
+ ---
424
+
425
+ ### 5.5 移除 Worktree
426
+
427
+ **命令:**
428
+
429
+ ```bash
430
+ clawt remove [options]
431
+ ```
432
+
433
+ **参数:**
434
+
435
+ | 参数 | 说明 |
436
+ | --------- | ---------------------------------------------------------- |
437
+ | `--all` | 移除当前项目 (`~/.clawt/worktrees/<project>/`) 下所有 worktree |
438
+ | `-b <branchName>` | 移除指定 branchName 下的所有 worktree |
439
+ | `-b <branchName> -i <index>` | 移除指定 branchName 的某一个 worktree (如 `branchName-2`) |
440
+
441
+ **三种移除粒度:**
442
+
443
+ | 粒度 | 命令示例 | 移除范围 |
444
+ | ---- | ---------------------------------------- | ------------------------------------------------------------- |
445
+ | 全部 | `clawt remove --all` | `~/.clawt/worktrees/<project>/` 下所有 worktree |
446
+ | 分支 | `clawt remove -b feature-scheme` | `~/.clawt/worktrees/<project>/feature-scheme-*` 的所有 worktree |
447
+ | 单个 | `clawt remove -b feature-scheme -i 2` | 仅移除 `~/.clawt/worktrees/<project>/feature-scheme-2` |
448
+
449
+ **运行流程:**
450
+
451
+ 1. **主 worktree 校验** (2.1)
452
+ 2. **获取项目名** (2.2)
453
+ 3. 根据参数确定要移除的 worktree 列表
454
+ 4. 列出即将移除的 worktree 及对应分支:
455
+
456
+ ```
457
+ 即将移除以下 worktree 及本地分支:
458
+
459
+ 1. ~/.clawt/worktrees/main-project/feature-scheme-1 → 分支: feature-scheme-1
460
+ 2. ~/.clawt/worktrees/main-project/feature-scheme-2 → 分支: feature-scheme-2
461
+ 3. ~/.clawt/worktrees/main-project/feature-scheme-3 → 分支: feature-scheme-3
462
+
463
+ 是否同时删除对应的本地分支?(y/N)
464
+ ```
465
+
466
+ 5. 用户确认后(只需确认一次),依次执行:
467
+
468
+ ```bash
469
+ # 移除 worktree
470
+ git worktree remove -f <worktree路径>
471
+
472
+ # 如果用户选择了删除分支
473
+ git branch -D <branchName>
474
+ ```
475
+
476
+ 6. 如果配置文件 `~/.clawt/config.json` 中 `autoDeleteBranch` 为 `true`,则跳过询问,直接删除分支。
477
+
478
+ 7. 移除完成后,清理空目录(如果 `~/.clawt/worktrees/<project>/` 下已无 worktree,则删除该项目目录)。
479
+
480
+ ---
481
+
482
+ ### 5.6 合并验证过的分支
483
+
484
+ **命令:**
485
+
486
+ ```bash
487
+ clawt merge -b <branchName> [-m <commitMessage>]
488
+ ```
489
+
490
+ **参数:**
491
+
492
+ | 参数 | 必填 | 说明 |
493
+ | ---- | ---- | ---------------------------------------- |
494
+ | `-b` | 是 | 要合并的分支名 |
495
+ | `-m` | 否 | 提交信息(目标 worktree 工作区有修改时必填) |
496
+
497
+ **运行流程:**
498
+
499
+ 1. **主 worktree 校验** (2.1)
500
+ 2. **主 worktree 状态检测**
501
+ - 执行 `git status --porcelain`
502
+ - 如果有更改 → 提示 `主 worktree 有未提交的更改,请先处理`,退出
503
+ - 无更改 → 继续
504
+ 3. **根据目标 worktree 状态决定是否需要提交**
505
+ - 检测目标 worktree 工作区是否干净(`git status --porcelain`)
506
+ - **工作区有未提交修改**:
507
+ - 如果用户未提供 `-m`,提示 `目标 worktree 有未提交的修改,请通过 -m 参数提供提交信息`,退出
508
+ - 提供了 `-m` → 执行提交:
509
+ ```bash
510
+ cd ~/.clawt/worktrees/<project>/<branchName>
511
+ git add .
512
+ git commit -m '<commitMessage>'
513
+ ```
514
+ - **工作区干净**:
515
+ - 检查目标分支相对于主分支是否有本地提交(`git log HEAD..<branchName> --oneline`)
516
+ - 有本地提交 → 跳过提交步骤,直接进入合并
517
+ - 无本地提交 → 提示 `目标 worktree 没有任何可合并的变更(工作区干净且无本地提交)`,退出
518
+ 4. **回到主 worktree 进行合并**
519
+ ```bash
520
+ cd <主 worktree 路径>
521
+ git merge <branchName>
522
+ ```
523
+ 5. **冲突检测**
524
+ - 检查 merge 退出码及 `git status` 是否存在冲突
525
+ - **有冲突** → 提示 `合并存在冲突,请手动处理`,退出
526
+ - **无冲突** → 继续
527
+ 6. **推送**
528
+ ```bash
529
+ git pull
530
+ git push
531
+ ```
532
+ 7. **输出成功提示**
533
+
534
+ ```
535
+ # 提供了 -m 时
536
+ ✓ 分支 feature-scheme-1 已成功合并到当前分支
537
+ 提交信息: <commitMessage>
538
+ 已推送到远程仓库
539
+
540
+ # 未提供 -m 时(目标 worktree 已提交过)
541
+ ✓ 分支 feature-scheme-1 已成功合并到当前分支
542
+ 已推送到远程仓库
543
+ ```
544
+
545
+ 8. **merge 成功后清理 worktree 和分支(可选)**
546
+ - 如果配置文件中 `autoDeleteBranch` 为 `true`,自动执行清理
547
+ - 否则交互式询问用户是否清理
548
+ - 用户确认后,依次执行:
549
+ ```bash
550
+ # 移除 worktree
551
+ git worktree remove -f <worktree路径>
552
+ # 删除本地分支
553
+ git branch -D <branchName>
554
+ # 修剪 worktree 引用
555
+ git worktree prune
556
+ # 如果项目 worktree 目录为空,则清理空目录
557
+ ```
558
+ - 输出清理成功提示:`✓ 已清理 worktree 和分支: <branchName>`
559
+
560
+ > **注意:** 清理确认在 merge 操作之前询问(避免 merge 成功后因交互中断而遗留未清理的 worktree),但清理操作在 merge 成功后才执行。
561
+
562
+ ---
563
+
564
+ ### 5.7 默认配置文件
565
+
566
+ **路径:** `~/.clawt/config.json`
567
+
568
+ **生成时机:** npm 全局安装后自动生成(通过 npm 的 `postinstall` 脚本)。
569
+
570
+ **升级策略:** 配置文件已存在时,执行增量合并而非简单跳过:
571
+
572
+ - **新版本新增的配置项** → 使用默认值补充到用户配置中
573
+ - **用户已有的配置项** → 保留用户的值,不覆盖
574
+ - **新版本已移除的配置项** → 从用户配置中删除
575
+
576
+ 仅在合并后配置发生变化时才写入文件。配置文件损坏或无法解析时,视为不存在,重新生成默认配置。
577
+
578
+ **默认内容:**
579
+
580
+ ```json
581
+ {
582
+ "autoDeleteBranch": false,
583
+ "claudeCodeCommand": "claude"
584
+ }
585
+ ```
586
+
587
+ **配置项说明:**
588
+
589
+ | 配置项 | 类型 | 默认值 | 说明 |
590
+ | ------------------ | --------- | --------- | -------------------------------------------------- |
591
+ | `autoDeleteBranch` | `boolean` | `false` | 移除 worktree 时是否自动删除对应本地分支(无需每次确认);merge 成功后是否自动清理 worktree 和分支;run 任务被中断(Ctrl+C)后是否自动清理本次创建的 worktree 和分支 |
592
+ | `claudeCodeCommand` | `string` | `"claude"` | Claude Code CLI 启动指令,用于 `clawt run` 不传 `--tasks` 时在 worktree 中打开交互式界面 |
593
+
594
+ ---
595
+
596
+ ### 5.8 获取当前项目所有 Worktree
597
+
598
+ **命令:**
599
+
600
+ ```bash
601
+ clawt list
602
+ ```
603
+
604
+ **运行流程:**
605
+
606
+ 1. **主 worktree 校验** (2.1)
607
+ 2. **获取项目名** (2.2)
608
+ 3. 扫描 `~/.clawt/worktrees/<project>/` 目录
609
+ 4. 对每个子目录,验证是否为有效的 git worktree(`git worktree list` 交叉验证)
610
+ 5. 输出列表
611
+
612
+ **输出格式:**
613
+
614
+ ```
615
+ 当前项目: main-project
616
+
617
+ ~/.clawt/worktrees/main-project/feature-scheme-1 [feature-scheme-1]
618
+ ~/.clawt/worktrees/main-project/feature-scheme-2 [feature-scheme-2]
619
+ ~/.clawt/worktrees/main-project/feature-scheme-3 [feature-scheme-3]
620
+ ~/.clawt/worktrees/main-project/bugfix-login [bugfix-login]
621
+
622
+ 共 4 个 worktree
623
+ ```
624
+
625
+ 如果没有 worktree:
626
+
627
+ ```
628
+ 当前项目: main-project
629
+
630
+ (无 worktree)
631
+ ```
632
+
633
+ ---
634
+
635
+ ### 5.9 日志系统
636
+
637
+ **日志目录:** `~/.clawt/logs/`
638
+
639
+ **日志文件命名:** `clawt-YYYY-MM-DD.log`(按日期滚动)
640
+
641
+ **日志级别:**
642
+
643
+ | 级别 | 说明 | 使用场景 |
644
+ | ------- | ------------------ | -------------------------------------- |
645
+ | `debug` | 调试信息 | Git 命令执行详情、变量值等 |
646
+ | `info` | 一般信息 | 操作开始/完成、创建/移除 worktree 等 |
647
+ | `warn` | 警告信息 | 分支名被转换、非致命异常等 |
648
+ | `error` | 错误信息 | 命令执行失败、校验不通过等 |
649
+
650
+ **实现方案:** 使用 `winston` + `winston-daily-rotate-file` 库。
651
+
652
+ **日志格式:**
653
+
654
+ ```
655
+ [2025-02-06 14:30:22] [INFO] 创建 worktree: ~/.clawt/worktrees/main-project/feature-scheme-1
656
+ [2025-02-06 14:30:22] [DEBUG] 执行命令: git worktree add -b feature-scheme-1 ~/.clawt/worktrees/main-project/feature-scheme-1
657
+ [2025-02-06 14:30:23] [WARN] 分支名已转换: feature/a.b → feature-a-b
658
+ [2025-02-06 14:30:25] [ERROR] 分支 feature-scheme-1 已存在,无法创建
659
+ ```
660
+
661
+ **保留策略:**
662
+
663
+ - 日志文件保留 30 天
664
+ - 单个日志文件最大 10MB
665
+
666
+ ---
667
+
668
+ ## 6. 错误处理规范
669
+
670
+ ### 6.1 通用错误处理
671
+
672
+ | 错误场景 | 处理方式 |
673
+ | --------------------------------- | ---------------------------------------------------------- |
674
+ | 不在主 worktree 根目录执行 | 输出错误提示,退出 (exit code 1) |
675
+ | Git 未安装 | 输出错误提示,退出 (exit code 1) |
676
+ | Claude Code CLI 未安装 | 输出错误提示,退出 (exit code 1)(仅 `clawt run` 时检测) |
677
+ | 分支已存在 | 输出错误提示,退出 (exit code 1) |
678
+ | Worktree 路径已存在 | 输出错误提示,退出 (exit code 1) |
679
+ | Git 命令执行失败 | 捕获 stderr,记录日志,输出错误提示,退出 (exit code 1) |
680
+ | 目标 worktree 不存在 | 输出错误提示(列出可用 worktree),退出 (exit code 1) |
681
+
682
+ ### 6.2 退出码
683
+
684
+ | 退出码 | 说明 |
685
+ | ------ | -------------- |
686
+ | `0` | 成功 |
687
+ | `1` | 一般错误 |
688
+ | `2` | 参数错误 |
689
+
690
+ ---
691
+
692
+ ## 7. 非功能性需求
693
+
694
+ ### 7.1 性能
695
+
696
+ - Worktree 创建为串行执行(Git worktree 不支持并行写入)
697
+ - Claude Code 任务为并行执行(各自独立进程)
698
+ - 任务完成检测:监听子进程 `close` 事件,事件驱动
699
+
700
+ ### 7.2 兼容性
701
+
702
+ - 支持 macOS 和 Linux
703
+ - Node.js >= 18
704
+ - Git >= 2.15(worktree 功能稳定版本)
705
+
706
+ ### 7.3 安全性
707
+
708
+ - 不在日志中记录 Claude Code API 密钥等敏感信息
709
+ - `--permission-mode bypassPermissions` 仅在 worktree 隔离环境中使用
710
+ - 所有用户输入(分支名等)都需要校验和转义