clawt 3.7.0 → 3.7.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/docs/run.md ADDED
@@ -0,0 +1,146 @@
1
+ ### 5.2 批量创建 Worktree + 执行 Claude Code 任务
2
+
3
+ > **注意:** run 命令内部调用 `createWorktrees` 或 `createWorktreesByBranches`,因此验证分支的创建和主工作分支检测逻辑(包括工作区脏状态处理)**自动继承** create 命令的变更,无需额外修改 run 命令本身。
4
+
5
+ **命令:**
6
+
7
+ ```bash
8
+ # 方式一:通过 --tasks 参数直接指定任务(多任务并行,支持 variadic 语法)
9
+ clawt run -b <branchName> --tasks <task1> <task2> <task3>
10
+
11
+ # 方式二:通过 -f 从任务文件读取任务列表
12
+ clawt run -f <path>
13
+
14
+ # 方式三:不传 --tasks 也不传 -f,在 worktree 中打开 Claude Code 交互式界面
15
+ clawt run -b <branchName>
16
+ ```
17
+
18
+ **参数:**
19
+
20
+ | 参数 | 必填 | 说明 |
21
+ | --------- | ---- | ----------------------------------------------------------- |
22
+ | `-b` | 否 | 分支名(使用 `-f` 时可选,否则必填) |
23
+ | `--tasks` | 否 | 任务描述(可多次指定,每个 --tasks 对应一个任务,任务数量即 worktree 数量)。不传则在 worktree 中打开 Claude Code 交互式界面 |
24
+ | `-f` | 否 | 从任务文件读取任务列表(与 `--tasks` 互斥) |
25
+ | `-c` | 否 | 最大并发数,`0` 表示不限制 |
26
+ | `--dry-run` | 否 | 试运行模式,仅输出预览信息不实际执行 |
27
+
28
+ **互斥约束:**
29
+
30
+ - `--file` 和 `--tasks` **不能同时使用**
31
+ - 非 `-f` 模式必须指定 `-b`
32
+
33
+ **交互式 Claude Code 界面模式:**
34
+
35
+ 当不传 `--tasks` 也不传 `-f` 时,会创建单个 worktree,然后通过 `spawnSync` + `inherit stdio` 在该 worktree 中直接启动 Claude Code CLI 交互式界面,让用户与 Claude Code 直接交互。
36
+
37
+ 启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,支持自定义命令及参数。
38
+
39
+ #### 任务文件格式
40
+
41
+ 任务文件使用嵌入 HTML 注释标签的自定义格式,不限制文件类型,标签外的任何文本都不会被解析。
42
+
43
+ ```markdown
44
+ 这里可以写任何说明文字,会被忽略
45
+
46
+ <!-- CLAWT-TASKS:START -->
47
+ # branch: feat-login
48
+ 实现用户登录功能
49
+ <!-- CLAWT-TASKS:END -->
50
+
51
+ <!-- CLAWT-TASKS:START -->
52
+ # branch: fix-bug
53
+ 修复内存泄漏问题
54
+ 这是多行任务描述
55
+ 可以写很多行
56
+ <!-- CLAWT-TASKS:END -->
57
+ ```
58
+
59
+ **格式规则:**
60
+
61
+ 1. **任务块界定**:每个任务用 `<!-- CLAWT-TASKS:START -->` 和 `<!-- CLAWT-TASKS:END -->` 包裹
62
+ 2. **分支名声明**:块内必须有一行 `# branch: <分支名>`(冒号前后的空格可灵活)
63
+ 3. **任务描述**:块内除分支名行以外的所有行,合并为任务描述(支持多行)
64
+ 4. **块外内容忽略**:标签外的任何文本都不会被解析
65
+ 5. **必填校验**:每个块必须包含任务描述;分支名默认必填,但使用 `-b` 参数时分支名为可选(会被忽略,用 `-b` 值自动编号)
66
+
67
+ **解析实现:** `src/utils/task-file.ts` 中的 `parseTaskFile()`、`loadTaskFile()` 和 `parseTasksFromOptions()` 函数,类型定义为 `TaskFileEntry`(`src/types/taskFile.ts`)。
68
+
69
+ #### 任务文件模式运行流程
70
+
71
+ 使用 `-f` 时的执行路径(`handleRun` → `handleRunFromFile`):
72
+
73
+ 1. 调用 `loadTaskFile(options.file)` 读取解析文件
74
+ 2. **有 `-b` 参数**:忽略文件中的分支名,用 `-b` 值自动编号创建 worktree(`createWorktrees(branch, count)`)
75
+ 3. **无 `-b` 参数**:使用文件中每个任务的独立分支名,先 `sanitizeBranchName` 清理后调用 `createWorktreesByBranches(branches)`
76
+ 4. 调用 `executeBatchTasks(worktrees, tasks, concurrency)` 执行
77
+
78
+ #### --tasks 模式运行流程
79
+
80
+ 1. 若传了 `--tasks`,解析得到任务数组 `tasks[]`;若未传,先检测分支是否已存在(已存在则提示使用 `clawt resume -b <branchName>` 恢复会话),然后创建单个 worktree 并启动 Claude Code 交互式界面(流程结束,不进入后续并行执行阶段)
81
+ 2. `n = tasks.length`
82
+ 3. 按照 **5.1** 的流程创建 `n` 个 worktree
83
+ 4. 通过公共函数 `executeBatchTasks`(`src/utils/task-executor.ts`)启动批量任务执行,该函数负责进度面板渲染、SIGINT 中断处理、并发控制和汇总输出。对每个 worktree 并行启动 Claude Code CLI:
84
+ ```bash
85
+ cd ~/.clawt/worktrees/<project>/<branchName>-<i>
86
+ claude -p "<tasks[i]>" --output-format stream-json --verbose --permission-mode bypassPermissions
87
+ ```
88
+ 使用 `stream-json` 格式可实时获取 Claude Code 的流式事件(工具调用、文本输出、最终结果),用于在进度面板中显示每个任务的实时活动描述和结果预览。流式事件解析由 `src/utils/stream-parser.ts` 负责。
89
+ 5. 进入**事件监听通知**阶段(见 [5.3](#53-任务完成通知机制))
90
+ 6. **中断处理(Ctrl+C / SIGINT)**
91
+ - 监听 `SIGINT` 信号,用户按下 Ctrl+C 时触发
92
+ - 向所有正在运行的 Claude Code 子进程发送 `SIGTERM` 终止信号
93
+ - 等待所有子进程退出后,进入清理流程:
94
+ - 如果 `autoDeleteBranch` 为 `true`:自动清理本次创建的所有 worktree 和对应分支
95
+ - 否则:交互式询问用户是否移除刚刚创建的 worktree 和对应分支
96
+ - 用户选择保留时,提示可使用 `clawt remove` 手动清理
97
+ - 清理完成后以退出码 `1` 退出
98
+
99
+ **注意:** 当 `n = 1` 时(只有一个任务),worktree 目录命名规则同 **5.1**(不加 `-1` 后缀)。
100
+
101
+ #### `--dry-run` 预览模式
102
+
103
+ 传入 `--dry-run` 时不实际创建 worktree 和执行任务,仅输出预览信息供用户确认。预览由 `printDryRunPreview()`(`src/utils/dry-run.ts`)负责渲染。
104
+
105
+ **输出格式:**
106
+
107
+ ```
108
+ ════════════════════════════════════════
109
+ Dry Run 预览
110
+ ════════════════════════════════════════
111
+ 任务数: 3 │ 并发数: 不限制 │ Worktree: ~/.clawt/worktrees/project
112
+ ────────────────────────────────────────
113
+ ✓ [1/3] feat-login
114
+ 路径: ~/.clawt/worktrees/project/feat-login
115
+ 任务: 实现登录功能
116
+
117
+ ⚠ [2/3] feat-signup — 分支 feat-signup 已存在
118
+ 路径: ~/.clawt/worktrees/project/feat-signup
119
+ 任务: 实现注册功能
120
+
121
+ ✓ [3/3] fix-bug
122
+ 路径: ~/.clawt/worktrees/project/fix-bug
123
+ 任务: 修复内存泄漏
124
+
125
+ ════════════════════════════════════════
126
+ ✓ 预览完成,无冲突。移除 --dry-run 即可正式执行。
127
+ ```
128
+
129
+ **格式规则:**
130
+
131
+ 1. **标题区**:双线分隔符包裹标题 `Dry Run 预览`
132
+ 2. **摘要行**:任务数、并发数、Worktree 目录路径合并为一行,用灰色 `│` 分隔;交互式模式(无 `--tasks`)会额外追加模式信息
133
+ 3. **分支列表**:
134
+ - 正常分支:行首绿色 `✓` + 序号 + 青色分支名
135
+ - 冲突分支:行首黄色 `⚠` + 序号 + 黄色分支名 + 灰色 `—` + 黄色警告文本(如 `分支 xxx 已存在`),警告合并在序号行
136
+ 4. **路径/任务行**:2 空格缩进,灰色标签前缀(`路径:` / `任务:`)
137
+ 5. **任务描述截断**:超过 80 字符时末尾加 `...`,多行合并为单行
138
+ 6. **结尾**:双线分隔符后根据冲突情况输出结论——无冲突时绿色 `✓` 提示,有冲突时黄色 `⚠` 警告
139
+
140
+ **实现要点:**
141
+
142
+ - 常量定义在 `src/constants/messages/run.ts`(`DRY_RUN_*` 系列)
143
+ - `DRY_RUN_WORKTREE_DIR` 前缀为 `Worktree:`(简短形式)
144
+ - `truncateTaskDesc()` 负责截断任务描述(最大长度 80 字符,定义在 `src/utils/dry-run.ts`)
145
+
146
+ ---
package/docs/spec.md ADDED
@@ -0,0 +1,428 @@
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
+ - [2.5 验证分支](#25-验证分支)
13
+ - [2.6 项目级配置](#26-项目级配置)(详见 [project-config.md](./project-config.md))
14
+ - [2.7 通用交互式配置编辑器](#27-通用交互式配置编辑器)
15
+ - [3. 全局目录结构](#3-全局目录结构)
16
+ - [4. 命令总览](#4-命令总览)
17
+ - [5. 需求场景详细设计](#5-需求场景详细设计)
18
+ - [5.1 批量创建 Worktree](./create.md)
19
+ - [5.2 批量创建 Worktree + 执行 Claude Code 任务](./run.md)
20
+ - [5.3 任务完成通知机制](./notification.md)
21
+ - [5.4 在主 Worktree 验证其他分支](./validate.md)
22
+ - [5.5 移除 Worktree](./remove.md)
23
+ - [5.6 合并验证过的分支](./merge.md)
24
+ - [5.7 默认配置文件](./config-file.md)
25
+ - [5.8 获取当前项目所有 Worktree](./list.md)
26
+ - [5.9 日志系统](./log.md)
27
+ - [5.10 交互式查看和修改全局配置](./config.md)
28
+ - [5.11 在已有 Worktree 中恢复会话](./resume.md)
29
+ - [5.12 将主分支代码同步到目标 Worktree](./sync.md)
30
+ - [5.13 重置主 Worktree 工作区和暂存区](./reset.md)
31
+ - [5.14 项目全局状态总览](./status.md)
32
+ - [5.15 命令别名管理](./alias.md)
33
+ - [5.16 Shell 自动补全](./completion.md)
34
+ - [5.17 自动更新检查](./update-check.md)
35
+ - [5.18 跨项目 Worktree 概览](./projects.md)
36
+ - [5.19 初始化项目级配置](./init.md)
37
+ - [5.20 切换回主工作分支](./home.md)
38
+ - [5.21 将验证分支修改覆盖回目标 Worktree](./cover-validate.md)
39
+ - [5.22 任务文件管理](./tasks.md)
40
+ - [6. 验证架构规则](#6-验证架构规则)
41
+ - [7. 错误处理规范](#7-错误处理规范)
42
+ - [8. 非功能性需求](#8-非功能性需求)
43
+ - [8.1 性能](#81-性能)
44
+ - [8.2 兼容性](#82-兼容性)
45
+ - [8.3 测试](#83-测试)
46
+ - [8.4 安全性](#84-安全性)
47
+
48
+ ---
49
+
50
+ ## 1. 技术栈
51
+
52
+ | 类别 | 选型 |
53
+ | -------- | ----------------------------- |
54
+ | 运行时 | Node.js >= 18 |
55
+ | 语言 | TypeScript |
56
+ | 包管理 | pnpm |
57
+ | CLI 框架 | Commander.js |
58
+ | 日志库 | winston (按日期滚动文件) |
59
+ | 交互式 | enquirer (选项选择/确认对话) |
60
+ | 终端宽度 | string-width (ANSI 安全的字符宽度计算) |
61
+ | 测试 | Vitest + @vitest/coverage-v8 |
62
+ | 构建 | tsup / tsc |
63
+ | 分发 | pnpm 全局安装 (`pnpm add -g clawt`) |
64
+
65
+ ---
66
+
67
+ ## 2. 核心概念
68
+
69
+ ### 2.1 "主 Worktree" 的定义与定位规则
70
+
71
+ **主 worktree** = `git rev-parse --git-common-dir` 所在的原始 worktree。
72
+
73
+ **强制约束:**
74
+
75
+ - `clawt` 命令 **只能** 在主 worktree 的仓库**根目录**执行。
76
+ - 校验条件:`git rev-parse --git-common-dir === ".git"`
77
+ - 如果不等于 `.git`(例如返回了绝对路径如 `/xxx/.git`),说明当前目录是子 worktree 或子目录,必须拒绝执行并提示用户。
78
+ - 还需校验当前目录是否为仓库根目录(存在 `.git` 目录)。
79
+
80
+ **校验伪代码:**
81
+
82
+ ```typescript
83
+ const gitCommonDir = execSync('git rev-parse --git-common-dir').toString().trim();
84
+ if (gitCommonDir !== '.git') {
85
+ // 报错:请在主 worktree 的根目录下执行 clawt
86
+ process.exit(1);
87
+ }
88
+ ```
89
+
90
+ ### 2.2 项目名获取
91
+
92
+ ```bash
93
+ project=$(basename "$(git rev-parse --show-toplevel)")
94
+ ```
95
+
96
+ 等价 TypeScript:
97
+
98
+ ```typescript
99
+ const projectRoot = execSync('git rev-parse --show-toplevel').toString().trim();
100
+ const projectName = path.basename(projectRoot);
101
+ ```
102
+
103
+ ### 2.3 分支名合法性校验与转换
104
+
105
+ 用户提供的 `branchName` 需要校验,凡是会影响文件系统路径 `~/.clawt/worktrees/<project>/<branchName>` 的非法字符,一律替换为 `-`。
106
+
107
+ **非法字符列表(至少包含):**
108
+
109
+ | 字符 | 说明 |
110
+ | ------- | ------------------------------ |
111
+ | `/` | 路径分隔符 |
112
+ | `\` | 路径分隔符(Windows) |
113
+ | `.` | 可能导致隐藏目录 |
114
+ | `..` | 目录遍历 |
115
+ | ` ` | 空格 |
116
+ | `~` | Home 目录展开 |
117
+ | `:` | Windows 驱动器号 / 特殊用途 |
118
+ | `*` | 通配符 |
119
+ | `?` | 通配符 |
120
+ | `[` `]` | 通配符 |
121
+ | `^` | Git ref 特殊字符 |
122
+
123
+ **转换规则:**
124
+
125
+ 1. 将所有非法字符替换为 `-`
126
+ 2. 将连续的 `-` 压缩为一个 `-`
127
+ 3. 去除首尾 `-`
128
+ 4. 如果转换后结果为空串(原始分支名不包含任何合法字符),报错退出
129
+
130
+ **示例输出:**
131
+
132
+ ```
133
+ 原始分支名: feature/a.b
134
+ 实际使用分支名: feature-a-b
135
+ ```
136
+
137
+ 如果发生了转换,**必须**在终端输出提示告知用户。
138
+
139
+ ### 2.4 分支名存在性校验
140
+
141
+ 创建前先检验分支名是否已经存在:
142
+
143
+ ```bash
144
+ git show-ref --verify refs/heads/<branchName> 2>/dev/null
145
+ ```
146
+
147
+ - 有输出 → 分支已存在 → 报错并退出
148
+ - 无输出 → 分支不存在 → 可以继续
149
+
150
+ > 注意:当 `n > 1` 时,需要校验的是 `branchName-1`、`branchName-2`、……、`branchName-n` 这些分支名。只要有一个已存在,就报错并退出(在创建任何 worktree 之前完成全部校验)。
151
+
152
+ ### 2.5 验证分支
153
+
154
+ validate 命令通过创建**验证分支**(validate branch)来杜绝 patch apply 冲突。每个目标 worktree 对应一个验证分支,validate 时在主 worktree 中切换到验证分支后再 apply patch,而不是在主工作分支上直接 apply。
155
+
156
+ #### 命名规则
157
+
158
+ 验证分支命名格式:`clawt-validate-<原始分支名>`
159
+
160
+ | 目标分支 | 验证分支 |
161
+ | --- | --- |
162
+ | `feat-login` | `clawt-validate-feat-login` |
163
+ | `fix-bug-1` | `clawt-validate-fix-bug-1` |
164
+ | `fix-bug-2` | `clawt-validate-fix-bug-2` |
165
+
166
+ #### 创建时机
167
+
168
+ 与目标 worktree 分支同时创建。在 `git worktree add -b <branchName>` 之后,立即执行:
169
+
170
+ ```bash
171
+ git branch clawt-validate-<branchName>
172
+ ```
173
+
174
+ 验证分支是一个普通的本地分支(不关联 worktree),指向创建时主 worktree 的 HEAD commit。
175
+
176
+ #### 为什么能杜绝冲突
177
+
178
+ 验证分支在创建后不会被修改(不受主分支 HEAD 推进的影响),它与目标 worktree 的分支共享同一个创建基点。因此 `git diff HEAD...<branchName> --binary` 中的 HEAD(验证分支的 HEAD)永远与目标分支的分叉点一致,patch apply 永远不会冲突。
179
+
180
+ #### 生命周期
181
+
182
+ 验证分支的生命周期与目标 worktree 的分支**完全一致**:
183
+
184
+ | 事件 | 目标分支 | 验证分支 |
185
+ | --- | --- | --- |
186
+ | create / run | 创建 | 同步创建 |
187
+ | remove(用户选择删除分支) | 删除 | 同步删除 |
188
+ | remove(用户选择保留分支) | 保留 | 保留 |
189
+ | merge 后清理(用户确认) | 删除 | 同步删除 |
190
+ | merge 后清理(用户拒绝) | 保留 | 保留 |
191
+ | sync | 不变 | 重建(删除后重新创建,基于当前主分支 HEAD) |
192
+
193
+ #### 验证分支前缀常量
194
+
195
+ 在 `src/constants/branch.ts` 中新增:
196
+
197
+ ```typescript
198
+ /** 验证分支名前缀 */
199
+ export const VALIDATE_BRANCH_PREFIX = 'clawt-validate-';
200
+ ```
201
+
202
+ ### 2.6 项目级配置
203
+
204
+ 每个 Git 项目独立的 clawt 配置,存放在 `~/.clawt/projects/<projectName>/config.json`。包含项目的主工作分支名(`clawtMainWorkBranch`)、validate 自动运行命令(`validateRunCommand`)等配置项。通过 `clawt init` 命令设置,核心命令执行前会校验该配置是否存在。
205
+
206
+ 详细的配置项列表、类型定义、工具函数和设置方式见 [项目级配置文档](./project-config.md)。
207
+
208
+ ### 2.7 通用交互式配置编辑器
209
+
210
+ `interactiveConfigEditor`(`src/utils/config-strategy.ts`)是一个通用的交互式配置编辑函数,供全局配置(`config` 命令)和项目级配置(`init show` 子命令)复用。
211
+
212
+ **函数签名:**
213
+
214
+ ```typescript
215
+ async function interactiveConfigEditor<T extends object>(
216
+ config: T,
217
+ definitions: Record<string, { description: string; allowedValues?: readonly string[] }>,
218
+ options?: { selectPrompt?: string; disabledKeys?: Record<string, string> },
219
+ ): Promise<{ key: keyof T; newValue: unknown }>
220
+ ```
221
+
222
+ **参数说明:**
223
+
224
+ | 参数 | 类型 | 说明 |
225
+ | --- | --- | --- |
226
+ | `config` | `T` | 当前配置对象 |
227
+ | `definitions` | `Record<string, { description; allowedValues? }>` | 配置项定义映射(含描述和可选枚举值) |
228
+ | `options.selectPrompt` | `string` | 可选,选择配置项的提示语(默认使用全局配置的提示语) |
229
+ | `options.disabledKeys` | `Record<string, string>` | 可选,不可编辑的键及其禁用提示文本 |
230
+
231
+ **行为:**
232
+
233
+ 1. 根据 `definitions` 构建选择列表,显示配置项名称、当前值(通过 `formatConfigValue` 格式化)和描述
234
+ 2. `disabledKeys` 中的配置项标灰不可选,显示禁用提示
235
+ 3. 用户选择配置项后,根据值类型自动选择输入方式(布尔 → Select、数字 → Input、字符串+枚举 → Select、字符串 → Input)
236
+ 4. 返回用户修改的 key 和新值,由调用方负责持久化
237
+
238
+ **调用场景:**
239
+
240
+ - `config` 命令:传入 `loadConfig()` + `CONFIG_DEFINITIONS` + `disabledKeys`(对象类型配置项禁用)
241
+ - `init show`:传入 `requireProjectConfig()` + `PROJECT_CONFIG_DEFINITIONS` + `selectPrompt`
242
+
243
+ 同时,`promptConfigValue` 和 `formatConfigValue` 的类型签名已从 `ClawtConfig` 专用类型放宽为通用类型(`string` / `unknown`),以支持不同配置体系复用。`formatConfigValue` 新增了 `undefined` / `null` 值的处理,显示为暗淡色的 `(未设置)`。
244
+
245
+ ---
246
+
247
+ ## 3. 全局目录结构
248
+
249
+ ```
250
+ ~/.clawt/
251
+ ├── config.json # 全局配置文件
252
+ ├── update-check.json # 更新检查缓存文件(自动生成)
253
+ ├── logs/ # 日志目录
254
+ │ ├── clawt-2025-02-06.log
255
+ │ └── ...
256
+ ├── validate-snapshots/ # validate 快照目录
257
+ │ └── <project-name>/ # 以项目名分组
258
+ │ ├── <branchName>.tree # 每个分支一个 tree hash 快照文件(存储 git tree 对象的 hash)
259
+ │ ├── <branchName>.head # 每个分支一个 HEAD commit hash 快照文件(存储快照时验证分支的 HEAD commit hash)
260
+ │ ├── <branchName>.staged # 每个分支一个 staged tree hash 快照文件(存储 validate 结束时暂存区对应的 tree hash,用于无变更时恢复)
261
+ │ └── ...
262
+ ├── projects/<project-name>/ # 项目级配置目录
263
+ │ └── config.json # 项目级配置(含 clawtMainWorkBranch)
264
+ └── worktrees/ # 所有 worktree 的统一存放目录
265
+ └── <project-name>/ # 以项目名分组
266
+ ├── <branchName>/ # n=1 时直接使用分支名
267
+ ├── <branchName>-1/ # n>1 时使用后缀编号
268
+ ├── <branchName>-2/
269
+ └── ...
270
+ ```
271
+
272
+ **注意:** 不需要支持多个不同路径下同名 repo 的区分。如果两个不同目录都叫 `main-project`,不做处理(视为同一个项目)。
273
+
274
+ ---
275
+
276
+ ## 4. 命令总览
277
+
278
+ | 命令 | 说明 | 对应场景 |
279
+ | --------------------- | ---------------------------------------------- | -------- |
280
+ | `clawt init` | 初始化项目级配置,设置主工作分支 | 5.19 |
281
+ | `clawt create` | 批量创建 worktree 及对应分支(含验证分支) | 5.1 |
282
+ | `clawt run` | 批量创建 worktree + 启动 Claude Code 执行任务(支持任务文件) | 5.2 |
283
+ | `clawt validate` | 在主 worktree 验证某个 worktree 分支的变更(通过验证分支)| 5.4 |
284
+ | `clawt merge` | 合并某个已验证的 worktree 分支到主 worktree | 5.6 |
285
+ | `clawt remove` | 移除 worktree(支持模糊匹配/多选/全部) | 5.5 |
286
+ | `clawt list` | 列出当前项目所有 worktree(支持 `--json` 格式输出) | 5.8 |
287
+ | `clawt config` | 交互式查看和修改全局配置 | 5.10 |
288
+ | `clawt config set` | 修改配置项(无参数进入交互式,有参数直接设置) | 5.10 |
289
+ | `clawt config get` | 获取单个配置项的值 | 5.10 |
290
+ | `clawt config reset` | 将配置恢复为默认值 | 5.10 |
291
+ | `clawt resume` | 在已有 worktree 中恢复 Claude Code 会话(支持多选批量恢复) | 5.11 |
292
+ | `clawt sync` | 将主分支最新代码同步到目标 worktree | 5.12 |
293
+ | `clawt reset` | 重置主 worktree 工作区和暂存区(保留 validate 快照) | 5.13 |
294
+ | `clawt status` | 显示项目全局状态总览(支持 `--json` 格式输出)| 5.14 |
295
+ | `clawt alias` | 管理命令别名(列出 / 设置 / 移除) | 5.15 |
296
+ | `clawt completion` | 为终端提供 shell 自动补全功能(bash/zsh) | 5.16 |
297
+ | `clawt projects` | 展示所有项目的 worktree 概览,或查看指定项目的 worktree 详情 | 5.18 |
298
+ | `clawt home` | 切换回主工作分支 | 5.20 |
299
+ | `clawt cover` | 将验证分支上的修改覆盖回目标 worktree(自动推导目标分支) | 5.21 |
300
+ | `clawt tasks` | 任务文件管理 | 5.22 |
301
+
302
+ **全局选项:**
303
+
304
+ | 选项 | 说明 |
305
+ | --------- | ---------------------------------------- |
306
+ | `--debug` | 输出详细调试信息到终端(启用 Console transport) |
307
+ | `-y, --yes` | 跳过所有交互式确认,适用于脚本/CI 环境 |
308
+
309
+ **环境变量:**
310
+
311
+ | 环境变量 | 说明 |
312
+ | -------- | ---- |
313
+ | `CI` | 设置为 `true` 或 `1` 时,自动启用非交互模式(等同于 `--yes`) |
314
+ | `CLAWT_NON_INTERACTIVE` | 设置为 `true` 或 `1` 时,自动启用非交互模式(等同于 `--yes`) |
315
+
316
+ > **非交互模式判断优先级:** CLI `--yes` 选项 > `CI` 环境变量 > `CLAWT_NON_INTERACTIVE` 环境变量 > 默认交互模式。实现见 `src/utils/interactive.ts`。
317
+
318
+ 所有命令执行前,都必须先执行**主 worktree 校验**(见 [2.1](#21-主-worktree-的定义与定位规则))。
319
+
320
+ ---
321
+
322
+ ## 5. 需求场景详细设计
323
+
324
+
325
+ - [5.1 批量创建 Worktree](./create.md)
326
+ - [5.2 批量创建 Worktree + 执行 Claude Code 任务](./run.md)
327
+ - [5.3 任务完成通知机制](./notification.md)
328
+ - [5.4 在主 Worktree 验证其他分支](./validate.md)
329
+ - [5.5 移除 Worktree](./remove.md)
330
+ - [5.6 合并验证过的分支](./merge.md)
331
+ - [5.7 默认配置文件](./config-file.md)
332
+ - [5.8 获取当前项目所有 Worktree](./list.md)
333
+ - [5.9 日志系统](./log.md)
334
+ - [5.10 交互式查看和修改全局配置](./config.md)
335
+ - [5.11 在已有 Worktree 中恢复会话](./resume.md)
336
+ - [5.12 将主分支代码同步到目标 Worktree](./sync.md)
337
+ - [5.13 重置主 Worktree 工作区和暂存区](./reset.md)
338
+ - [5.14 项目全局状态总览](./status.md)
339
+ - [5.15 命令别名管理](./alias.md)
340
+ - [5.16 Shell 自动补全](./completion.md)
341
+ - [5.17 自动更新检查](./update-check.md)
342
+ - [5.18 跨项目 Worktree 概览](./projects.md)
343
+ - [5.19 初始化项目级配置](./init.md)
344
+ - [5.20 切换回主工作分支](./home.md)
345
+ - [5.21 将验证分支修改覆盖回目标 Worktree](./cover-validate.md)
346
+ - [5.22 任务文件管理](./tasks.md)
347
+
348
+ ---
349
+
350
+ ## 6. 验证架构规则
351
+
352
+ 以下规则适用于验证分支架构的所有实现工作:
353
+
354
+ 1. **不兼容旧版本**:本次重构不考虑旧版本数据、旧版本创建的 worktree 或旧版本配置的兼容性。所有命令均假定验证分支和项目级配置已按新架构存在。用户需删除旧 worktree 后重新创建。
355
+ 2. **项目级配置前置校验**:仅对 create、run、validate、cover、sync、remove、merge、reset、home 这 9 个核心命令添加检测,执行时必须先检查项目级配置(`~/.clawt/projects/<projectName>/config.json`)是否存在且包含 `clawtMainWorkBranch`。如果不存在,直接报错退出并提示用户先执行 `clawt init`:
356
+ ```
357
+ ✗ 该项目尚未初始化,请先执行 clawt init -b<branchName>设置主工作分支
358
+ ```
359
+ 其他命令(list、resume、config、status、alias、projects、completion、tasks)不受影响,无需添加该校验。
360
+ > **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、sync、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。其中 sync 命令的 `PRE_CHECK_SYNC` 同时包含 `requireProjectConfig` 和 `ensureOnClawtMainWorkBranch`(因为 sync 需要在主工作分支上发起合并操作)。validate 命令虽然在 `--clean` 模式中调用了 `ensureOnMainWorkBranch`,但其主流程和 `--clean` 流程均显式调用了 `requireProjectConfig`。remove、cover、reset 和 home 命令因不依赖主 worktree 的分支状态而不调用 `ensureOnMainWorkBranch`,需自行显式调用 `requireProjectConfig()`。
361
+ 3. **主分支名统一从项目级配置获取**:所有需要获取主分支名的场景(sync 中合并主分支、merge 中计算 merge-base、切回主分支等),统一使用项目级配置中的 `clawtMainWorkBranch`,不再通过 `getCurrentBranch(mainWorktreePath)` 动态获取。因为在新架构下,主 worktree 可能处于验证分支上,`getCurrentBranch` 会返回验证分支名而非真正的主工作分支名。
362
+ 4. **测试文件全量更新**:本次重构涉及的所有命令(init、create、run、validate、sync、remove、merge、reset),其对应的测试文件必须同步更新,确保覆盖新增的验证分支逻辑、项目级配置逻辑和变更后的流程。
363
+
364
+ ---
365
+
366
+ ## 7. 错误处理规范
367
+
368
+ ### 7.1 通用错误处理
369
+
370
+ | 错误场景 | 处理方式 |
371
+ | --------------------------------- | ---------------------------------------------------------- |
372
+ | 不在主 worktree 根目录执行 | 输出错误提示,退出 (exit code 1) |
373
+ | Git 未安装 | 输出错误提示,退出 (exit code 1) |
374
+ | Claude Code CLI 未安装 | 输出错误提示,退出 (exit code 1)(`clawt run` 和 `clawt resume` 时检测) |
375
+ | 分支已存在 | 输出错误提示,退出 (exit code 1) |
376
+ | Worktree 路径已存在 | 输出错误提示,退出 (exit code 1) |
377
+ | Git 命令执行失败 | 捕获 stderr,记录日志,输出错误提示,退出 (exit code 1) |
378
+ | 目标 worktree 不存在 | 输出错误提示(列出可用 worktree),退出 (exit code 1) |
379
+
380
+ ### 7.2 退出码
381
+
382
+ | 退出码 | 说明 |
383
+ | ------ | -------------- |
384
+ | `0` | 成功 |
385
+ | `1` | 一般错误 |
386
+ | `2` | 参数错误 |
387
+
388
+ ---
389
+
390
+ ## 8. 非功能性需求
391
+
392
+ ### 8.1 性能
393
+
394
+ - Worktree 创建为串行执行(Git worktree 不支持并行写入)
395
+ - Claude Code 任务为并行执行(各自独立进程)
396
+ - 任务完成检测:监听子进程 `close` 事件,事件驱动
397
+
398
+ ### 8.2 兼容性
399
+
400
+ - 支持 macOS 和 Linux
401
+ - Node.js >= 18
402
+ - Git >= 2.15(worktree 功能稳定版本)
403
+
404
+ ### 8.3 测试
405
+
406
+ - 测试框架:Vitest,配置文件为 `vitest.config.ts`
407
+ - 覆盖率工具:@vitest/coverage-v8,覆盖率报告格式为 text、lcov、html
408
+ - 测试目录结构:`tests/unit/` 下按模块分组(`constants/`、`errors/`、`utils/`)
409
+ - 测试辅助文件:
410
+ - `tests/helpers/setup.ts`:全局 setup,禁用 chalk 颜色输出避免 ANSI 转义码干扰断言
411
+ - `tests/helpers/fixtures.ts`:测试数据工厂,提供 `createWorktreeInfo()`、`createWorktreeStatus()`、`createWorktreeList()` 等工厂函数
412
+ - 覆盖范围:`src/` 下的 `commands/`、`utils/`、`errors/`、`constants/` 全部关键模块
413
+ - 覆盖率统计排除项:`src/index.ts`(入口文件)、`src/types/**`(类型定义)、`src/logger/**`(日志模块)
414
+ - npm 脚本:
415
+ - `npm test`:执行全部测试(`vitest run`)
416
+ - `npm run test:watch`:监听模式(`vitest`)
417
+ - `npm run test:coverage`:执行测试并生成覆盖率报告(`vitest run --coverage`)
418
+ - 测试配置特性:
419
+ - `restoreMocks: true`:每个测试后自动恢复 mock
420
+ - `clearMocks: true`:每个测试后自动清除 mock 调用记录
421
+ - `testTimeout: 10000`:单个测试超时 10 秒
422
+ - `environment: 'node'`:使用 Node.js 测试环境
423
+
424
+ ### 8.4 安全性
425
+
426
+ - 不在日志中记录 Claude Code API 密钥等敏感信息
427
+ - `--permission-mode bypassPermissions` 仅在 worktree 隔离环境中使用
428
+ - 所有用户输入(分支名等)都需要校验和转义