clawt 2.19.0 → 3.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.
- package/README.md +12 -2
- package/dist/index.js +626 -219
- package/dist/postinstall.js +39 -6
- package/docs/alias.md +108 -0
- package/docs/completion.md +55 -0
- package/docs/config-file.md +43 -0
- package/docs/config.md +91 -0
- package/docs/create.md +85 -0
- package/docs/init.md +65 -0
- package/docs/list.md +67 -0
- package/docs/log.md +67 -0
- package/docs/merge.md +137 -0
- package/docs/notification.md +94 -0
- package/docs/projects.md +135 -0
- package/docs/remove.md +79 -0
- package/docs/reset.md +35 -0
- package/docs/resume.md +99 -0
- package/docs/run.md +146 -0
- package/docs/spec.md +156 -1879
- package/docs/status.md +155 -0
- package/docs/sync.md +114 -0
- package/docs/update-check.md +95 -0
- package/docs/validate.md +368 -0
- package/package.json +1 -1
- package/src/commands/alias.ts +1 -1
- package/src/commands/create.ts +10 -5
- package/src/commands/init.ts +75 -0
- package/src/commands/list.ts +1 -1
- package/src/commands/merge.ts +11 -4
- package/src/commands/remove.ts +10 -3
- package/src/commands/reset.ts +3 -0
- package/src/commands/resume.ts +9 -3
- package/src/commands/run.ts +9 -3
- package/src/commands/status.ts +1 -1
- package/src/commands/sync.ts +18 -6
- package/src/commands/validate.ts +46 -52
- package/src/constants/branch.ts +3 -0
- package/src/constants/config.ts +1 -1
- package/src/constants/index.ts +3 -3
- package/src/constants/messages/completion.ts +1 -1
- package/src/constants/messages/create.ts +3 -0
- package/src/constants/messages/index.ts +2 -0
- package/src/constants/messages/init.ts +18 -0
- package/src/constants/messages/remove.ts +2 -0
- package/src/constants/messages/sync.ts +3 -0
- package/src/constants/messages/validate.ts +6 -0
- package/src/constants/paths.ts +3 -0
- package/src/constants/prompt.ts +28 -0
- package/src/index.ts +2 -0
- package/src/types/command.ts +7 -1
- package/src/types/index.ts +2 -1
- package/src/types/projectConfig.ts +5 -0
- package/src/utils/config.ts +2 -1
- package/src/utils/git.ts +18 -0
- package/src/utils/index.ts +6 -1
- package/src/utils/json.ts +67 -0
- package/src/utils/project-config.ts +77 -0
- package/src/utils/validate-branch.ts +166 -0
- package/src/utils/worktree-matcher.ts +268 -1
- package/src/utils/worktree.ts +6 -2
- package/tests/unit/commands/create.test.ts +20 -16
- package/tests/unit/commands/init.test.ts +146 -0
- package/tests/unit/commands/merge.test.ts +7 -1
- package/tests/unit/commands/remove.test.ts +4 -0
- package/tests/unit/commands/reset.test.ts +2 -0
- package/tests/unit/commands/resume.test.ts +29 -8
- package/tests/unit/commands/run.test.ts +2 -0
- package/tests/unit/commands/sync.test.ts +6 -0
- package/tests/unit/commands/validate.test.ts +13 -0
- package/tests/unit/utils/config.test.ts +2 -2
- package/tests/unit/utils/project-config.test.ts +136 -0
- package/tests/unit/utils/update-checker.test.ts +28 -7
- package/tests/unit/utils/validate-branch.test.ts +272 -0
- package/tests/unit/utils/worktree-matcher.test.ts +142 -1
- package/tests/unit/utils/worktree.test.ts +6 -0
package/docs/spec.md
CHANGED
|
@@ -9,33 +9,37 @@
|
|
|
9
9
|
|
|
10
10
|
- [1. 技术栈](#1-技术栈)
|
|
11
11
|
- [2. 核心概念](#2-核心概念)
|
|
12
|
+
- [2.5 验证分支](#25-验证分支)
|
|
13
|
+
- [2.6 项目级配置](#26-项目级配置)
|
|
12
14
|
- [3. 全局目录结构](#3-全局目录结构)
|
|
13
15
|
- [4. 命令总览](#4-命令总览)
|
|
14
16
|
- [5. 需求场景详细设计](#5-需求场景详细设计)
|
|
15
|
-
- [5.1 批量创建 Worktree](
|
|
16
|
-
- [5.2 批量创建 Worktree + 执行 Claude Code 任务](
|
|
17
|
-
- [5.3 任务完成通知机制](
|
|
18
|
-
- [5.4 在主 Worktree 验证其他分支](
|
|
19
|
-
- [5.5 移除 Worktree](
|
|
20
|
-
- [5.6 合并验证过的分支](
|
|
21
|
-
- [5.7 默认配置文件](
|
|
22
|
-
- [5.8 获取当前项目所有 Worktree](
|
|
23
|
-
- [5.9 日志系统](
|
|
24
|
-
- [5.10 交互式查看和修改全局配置](
|
|
25
|
-
- [5.11 在已有 Worktree 中恢复会话](
|
|
26
|
-
- [5.12 将主分支代码同步到目标 Worktree](
|
|
27
|
-
- [5.13 重置主 Worktree 工作区和暂存区](
|
|
28
|
-
- [5.14 项目全局状态总览](
|
|
29
|
-
- [5.15 命令别名管理](
|
|
30
|
-
- [5.16 Shell 自动补全](
|
|
31
|
-
- [5.17 自动更新检查](
|
|
32
|
-
- [5.18 跨项目 Worktree 概览](
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- [
|
|
38
|
-
- [
|
|
17
|
+
- [5.1 批量创建 Worktree](./create.md)
|
|
18
|
+
- [5.2 批量创建 Worktree + 执行 Claude Code 任务](./run.md)
|
|
19
|
+
- [5.3 任务完成通知机制](./notification.md)
|
|
20
|
+
- [5.4 在主 Worktree 验证其他分支](./validate.md)
|
|
21
|
+
- [5.5 移除 Worktree](./remove.md)
|
|
22
|
+
- [5.6 合并验证过的分支](./merge.md)
|
|
23
|
+
- [5.7 默认配置文件](./config-file.md)
|
|
24
|
+
- [5.8 获取当前项目所有 Worktree](./list.md)
|
|
25
|
+
- [5.9 日志系统](./log.md)
|
|
26
|
+
- [5.10 交互式查看和修改全局配置](./config.md)
|
|
27
|
+
- [5.11 在已有 Worktree 中恢复会话](./resume.md)
|
|
28
|
+
- [5.12 将主分支代码同步到目标 Worktree](./sync.md)
|
|
29
|
+
- [5.13 重置主 Worktree 工作区和暂存区](./reset.md)
|
|
30
|
+
- [5.14 项目全局状态总览](./status.md)
|
|
31
|
+
- [5.15 命令别名管理](./alias.md)
|
|
32
|
+
- [5.16 Shell 自动补全](./completion.md)
|
|
33
|
+
- [5.17 自动更新检查](./update-check.md)
|
|
34
|
+
- [5.18 跨项目 Worktree 概览](./projects.md)
|
|
35
|
+
- [5.19 初始化项目级配置](./init.md)
|
|
36
|
+
- [6. 验证架构规则](#6-验证架构规则)
|
|
37
|
+
- [7. 错误处理规范](#7-错误处理规范)
|
|
38
|
+
- [8. 非功能性需求](#8-非功能性需求)
|
|
39
|
+
- [8.1 性能](#81-性能)
|
|
40
|
+
- [8.2 兼容性](#82-兼容性)
|
|
41
|
+
- [8.3 测试](#83-测试)
|
|
42
|
+
- [8.4 安全性](#84-安全性)
|
|
39
43
|
|
|
40
44
|
---
|
|
41
45
|
|
|
@@ -141,6 +145,91 @@ git show-ref --verify refs/heads/<branchName> 2>/dev/null
|
|
|
141
145
|
|
|
142
146
|
> 注意:当 `n > 1` 时,需要校验的是 `branchName-1`、`branchName-2`、……、`branchName-n` 这些分支名。只要有一个已存在,就报错并退出(在创建任何 worktree 之前完成全部校验)。
|
|
143
147
|
|
|
148
|
+
### 2.5 验证分支
|
|
149
|
+
|
|
150
|
+
validate 命令通过创建**验证分支**(validate branch)来杜绝 patch apply 冲突。每个目标 worktree 对应一个验证分支,validate 时在主 worktree 中切换到验证分支后再 apply patch,而不是在主工作分支上直接 apply。
|
|
151
|
+
|
|
152
|
+
#### 命名规则
|
|
153
|
+
|
|
154
|
+
验证分支命名格式:`clawt-validate-<原始分支名>`
|
|
155
|
+
|
|
156
|
+
| 目标分支 | 验证分支 |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| `feat-login` | `clawt-validate-feat-login` |
|
|
159
|
+
| `fix-bug-1` | `clawt-validate-fix-bug-1` |
|
|
160
|
+
| `fix-bug-2` | `clawt-validate-fix-bug-2` |
|
|
161
|
+
|
|
162
|
+
#### 创建时机
|
|
163
|
+
|
|
164
|
+
与目标 worktree 分支同时创建。在 `git worktree add -b <branchName>` 之后,立即执行:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
git branch clawt-validate-<branchName>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
验证分支是一个普通的本地分支(不关联 worktree),指向创建时主 worktree 的 HEAD commit。
|
|
171
|
+
|
|
172
|
+
#### 为什么能杜绝冲突
|
|
173
|
+
|
|
174
|
+
验证分支在创建后不会被修改(不受主分支 HEAD 推进的影响),它与目标 worktree 的分支共享同一个创建基点。因此 `git diff HEAD...<branchName> --binary` 中的 HEAD(验证分支的 HEAD)永远与目标分支的分叉点一致,patch apply 永远不会冲突。
|
|
175
|
+
|
|
176
|
+
#### 生命周期
|
|
177
|
+
|
|
178
|
+
验证分支的生命周期与目标 worktree 的分支**完全一致**:
|
|
179
|
+
|
|
180
|
+
| 事件 | 目标分支 | 验证分支 |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| create / run | 创建 | 同步创建 |
|
|
183
|
+
| remove(用户选择删除分支) | 删除 | 同步删除 |
|
|
184
|
+
| remove(用户选择保留分支) | 保留 | 保留 |
|
|
185
|
+
| merge 后清理(用户确认) | 删除 | 同步删除 |
|
|
186
|
+
| merge 后清理(用户拒绝) | 保留 | 保留 |
|
|
187
|
+
| sync | 不变 | 重建(删除后重新创建,基于当前主分支 HEAD) |
|
|
188
|
+
|
|
189
|
+
#### 验证分支前缀常量
|
|
190
|
+
|
|
191
|
+
在 `src/constants/branch.ts` 中新增:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
/** 验证分支名前缀 */
|
|
195
|
+
export const VALIDATE_BRANCH_PREFIX = 'clawt-validate-';
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 2.6 项目级配置
|
|
199
|
+
|
|
200
|
+
#### 存放位置
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
~/.clawt/projects/<projectName>/config.json
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
#### 配置内容
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"clawtMainWorkBranch": "main"
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
| 配置项 | 类型 | 说明 |
|
|
215
|
+
| --- | --- | --- |
|
|
216
|
+
| `clawtMainWorkBranch` | `string` | 项目的主工作分支名,用于 create 时检测当前分支是否为主分支 |
|
|
217
|
+
|
|
218
|
+
#### 设置方式
|
|
219
|
+
|
|
220
|
+
通过 `clawt init` 命令设置(见 [5.19 初始化项目级配置](#519-初始化项目级配置))。
|
|
221
|
+
|
|
222
|
+
除 `clawt init` 以外的所有核心命令(create、run、validate、sync、remove、merge、reset),执行时都会校验项目级配置是否存在。如果未执行过 `clawt init`,命令会直接报错并提示用户先初始化。
|
|
223
|
+
|
|
224
|
+
#### 路径常量
|
|
225
|
+
|
|
226
|
+
在 `src/constants/paths.ts` 中新增:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
/** 项目级配置目录 ~/.clawt/projects/ */
|
|
230
|
+
export const PROJECTS_CONFIG_DIR = join(CLAWT_HOME, 'projects');
|
|
231
|
+
```
|
|
232
|
+
|
|
144
233
|
---
|
|
145
234
|
|
|
146
235
|
## 3. 全局目录结构
|
|
@@ -155,8 +244,10 @@ git show-ref --verify refs/heads/<branchName> 2>/dev/null
|
|
|
155
244
|
├── validate-snapshots/ # validate 快照目录
|
|
156
245
|
│ └── <project-name>/ # 以项目名分组
|
|
157
246
|
│ ├── <branchName>.tree # 每个分支一个 tree hash 快照文件(存储 git tree 对象的 hash)
|
|
158
|
-
│ ├── <branchName>.head # 每个分支一个 HEAD commit hash
|
|
247
|
+
│ ├── <branchName>.head # 每个分支一个 HEAD commit hash 快照文件(存储快照时验证分支的 HEAD commit hash)
|
|
159
248
|
│ └── ...
|
|
249
|
+
├── projects/<project-name>/ # 项目级配置目录
|
|
250
|
+
│ └── config.json # 项目级配置(含 clawtMainWorkBranch)
|
|
160
251
|
└── worktrees/ # 所有 worktree 的统一存放目录
|
|
161
252
|
└── <project-name>/ # 以项目名分组
|
|
162
253
|
├── <branchName>/ # n=1 时直接使用分支名
|
|
@@ -173,9 +264,10 @@ git show-ref --verify refs/heads/<branchName> 2>/dev/null
|
|
|
173
264
|
|
|
174
265
|
| 命令 | 说明 | 对应场景 |
|
|
175
266
|
| --------------------- | ---------------------------------------------- | -------- |
|
|
176
|
-
| `clawt
|
|
267
|
+
| `clawt init` | 初始化项目级配置,设置主工作分支 | 5.19 |
|
|
268
|
+
| `clawt create` | 批量创建 worktree 及对应分支(含验证分支) | 5.1 |
|
|
177
269
|
| `clawt run` | 批量创建 worktree + 启动 Claude Code 执行任务(支持任务文件) | 5.2 |
|
|
178
|
-
| `clawt validate` | 在主 worktree 验证某个 worktree
|
|
270
|
+
| `clawt validate` | 在主 worktree 验证某个 worktree 分支的变更(通过验证分支)| 5.4 |
|
|
179
271
|
| `clawt merge` | 合并某个已验证的 worktree 分支到主 worktree | 5.6 |
|
|
180
272
|
| `clawt remove` | 移除 worktree(支持模糊匹配/多选/全部) | 5.5 |
|
|
181
273
|
| `clawt list` | 列出当前项目所有 worktree(支持 `--json` 格式输出) | 5.8 |
|
|
@@ -184,7 +276,7 @@ git show-ref --verify refs/heads/<branchName> 2>/dev/null
|
|
|
184
276
|
| `clawt config get` | 获取单个配置项的值 | 5.10 |
|
|
185
277
|
| `clawt config reset` | 将配置恢复为默认值 | 5.10 |
|
|
186
278
|
| `clawt resume` | 在已有 worktree 中恢复 Claude Code 会话(支持多选批量恢复) | 5.11 |
|
|
187
|
-
| `clawt sync` | 将主分支最新代码同步到目标 worktree
|
|
279
|
+
| `clawt sync` | 将主分支最新代码同步到目标 worktree(含验证分支重建) | 5.12 |
|
|
188
280
|
| `clawt reset` | 重置主 worktree 工作区和暂存区 | 5.13 |
|
|
189
281
|
| `clawt status` | 显示项目全局状态总览(支持 `--json` 格式输出) | 5.14 |
|
|
190
282
|
| `clawt alias` | 管理命令别名(列出 / 设置 / 移除) | 5.15 |
|
|
@@ -203,1863 +295,48 @@ git show-ref --verify refs/heads/<branchName> 2>/dev/null
|
|
|
203
295
|
|
|
204
296
|
## 5. 需求场景详细设计
|
|
205
297
|
|
|
206
|
-
### 5.1 批量创建 Worktree(Worktree 对应分支)
|
|
207
|
-
|
|
208
|
-
**命令:**
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
clawt create -b <branchName> [-n <count>]
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**参数:**
|
|
215
|
-
|
|
216
|
-
| 参数 | 必填 | 说明 |
|
|
217
|
-
| ---- | ---- | ----------------------------------------------------- |
|
|
218
|
-
| `-b` | 是 | 分支名 |
|
|
219
|
-
| `-n` | 否 | 需要创建的 worktree 数量,默认 `1` |
|
|
220
|
-
|
|
221
|
-
**运行流程:**
|
|
222
|
-
|
|
223
|
-
1. **主 worktree 校验** (2.1)
|
|
224
|
-
2. **获取项目名** (2.2)
|
|
225
|
-
3. **分支名合法性校验与转换** (2.3)
|
|
226
|
-
4. **分支名存在性校验** (2.4)
|
|
227
|
-
- 若 `n = 1`:校验 `branchName`
|
|
228
|
-
- 若 `n > 1`:校验 `branchName-1` 到 `branchName-n`
|
|
229
|
-
- 所有分支名在创建任何 worktree **之前**完成全部校验
|
|
230
|
-
5. **批量创建 worktree**
|
|
231
|
-
- 若 `n = 1`:
|
|
232
|
-
```bash
|
|
233
|
-
git worktree add -b <branchName> ~/.clawt/worktrees/<project>/<branchName>
|
|
234
|
-
```
|
|
235
|
-
- 若 `n > 1`:
|
|
236
|
-
```bash
|
|
237
|
-
git worktree add -b <branchName>-1 ~/.clawt/worktrees/<project>/<branchName>-1
|
|
238
|
-
git worktree add -b <branchName>-2 ~/.clawt/worktrees/<project>/<branchName>-2
|
|
239
|
-
...
|
|
240
|
-
git worktree add -b <branchName>-n ~/.clawt/worktrees/<project>/<branchName>-n
|
|
241
|
-
```
|
|
242
|
-
6. **输出创建日志**
|
|
243
|
-
|
|
244
|
-
**输出格式:**
|
|
245
298
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
299
|
+
- [5.1 批量创建 Worktree](./create.md)
|
|
300
|
+
- [5.2 批量创建 Worktree + 执行 Claude Code 任务](./run.md)
|
|
301
|
+
- [5.3 任务完成通知机制](./notification.md)
|
|
302
|
+
- [5.4 在主 Worktree 验证其他分支](./validate.md)
|
|
303
|
+
- [5.5 移除 Worktree](./remove.md)
|
|
304
|
+
- [5.6 合并验证过的分支](./merge.md)
|
|
305
|
+
- [5.7 默认配置文件](./config-file.md)
|
|
306
|
+
- [5.8 获取当前项目所有 Worktree](./list.md)
|
|
307
|
+
- [5.9 日志系统](./log.md)
|
|
308
|
+
- [5.10 交互式查看和修改全局配置](./config.md)
|
|
309
|
+
- [5.11 在已有 Worktree 中恢复会话](./resume.md)
|
|
310
|
+
- [5.12 将主分支代码同步到目标 Worktree](./sync.md)
|
|
311
|
+
- [5.13 重置主 Worktree 工作区和暂存区](./reset.md)
|
|
312
|
+
- [5.14 项目全局状态总览](./status.md)
|
|
313
|
+
- [5.15 命令别名管理](./alias.md)
|
|
314
|
+
- [5.16 Shell 自动补全](./completion.md)
|
|
315
|
+
- [5.17 自动更新检查](./update-check.md)
|
|
316
|
+
- [5.18 跨项目 Worktree 概览](./projects.md)
|
|
317
|
+
- [5.19 初始化项目级配置](./init.md)
|
|
262
318
|
|
|
263
319
|
---
|
|
264
320
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
**命令:**
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
# 方式一:通过 --tasks 参数直接指定任务(多任务并行)
|
|
271
|
-
clawt run -b <branchName> --tasks <task1> --tasks <task2> --tasks <task3>
|
|
272
|
-
|
|
273
|
-
# 方式二:通过 -f 从任务文件读取任务列表
|
|
274
|
-
clawt run -f <path>
|
|
275
|
-
|
|
276
|
-
# 方式三:不传 --tasks 也不传 -f,在 worktree 中打开 Claude Code 交互式界面
|
|
277
|
-
clawt run -b <branchName>
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
**参数:**
|
|
281
|
-
|
|
282
|
-
| 参数 | 必填 | 说明 |
|
|
283
|
-
| --------- | ---- | ----------------------------------------------------------- |
|
|
284
|
-
| `-b` | 否 | 分支名(使用 `-f` 时可选,否则必填) |
|
|
285
|
-
| `--tasks` | 否 | 任务描述(可多次指定,每个 --tasks 对应一个任务,任务数量即 worktree 数量)。不传则在 worktree 中打开 Claude Code 交互式界面 |
|
|
286
|
-
| `-f` | 否 | 从任务文件读取任务列表(与 `--tasks` 互斥) |
|
|
287
|
-
| `-c` | 否 | 最大并发数,`0` 表示不限制 |
|
|
288
|
-
| `--dry-run` | 否 | 试运行模式,仅输出预览信息不实际执行 |
|
|
289
|
-
|
|
290
|
-
**互斥约束:**
|
|
291
|
-
|
|
292
|
-
- `--file` 和 `--tasks` **不能同时使用**
|
|
293
|
-
- 非 `-f` 模式必须指定 `-b`
|
|
294
|
-
|
|
295
|
-
**交互式 Claude Code 界面模式:**
|
|
296
|
-
|
|
297
|
-
当不传 `--tasks` 也不传 `-f` 时,会创建单个 worktree,然后通过 `spawnSync` + `inherit stdio` 在该 worktree 中直接启动 Claude Code CLI 交互式界面,让用户与 Claude Code 直接交互。
|
|
298
|
-
|
|
299
|
-
启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,支持自定义命令及参数。
|
|
300
|
-
|
|
301
|
-
#### 任务文件格式
|
|
302
|
-
|
|
303
|
-
任务文件使用嵌入 HTML 注释标签的自定义格式,不限制文件类型,标签外的任何文本都不会被解析。
|
|
304
|
-
|
|
305
|
-
```markdown
|
|
306
|
-
这里可以写任何说明文字,会被忽略
|
|
321
|
+
## 6. 验证架构规则
|
|
307
322
|
|
|
308
|
-
|
|
309
|
-
# branch: feat-login
|
|
310
|
-
实现用户登录功能
|
|
311
|
-
<!-- CLAWT-TASKS:END -->
|
|
323
|
+
以下规则适用于验证分支架构的所有实现工作:
|
|
312
324
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
修复内存泄漏问题
|
|
316
|
-
这是多行任务描述
|
|
317
|
-
可以写很多行
|
|
318
|
-
<!-- CLAWT-TASKS:END -->
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
**格式规则:**
|
|
322
|
-
|
|
323
|
-
1. **任务块界定**:每个任务用 `<!-- CLAWT-TASKS:START -->` 和 `<!-- CLAWT-TASKS:END -->` 包裹
|
|
324
|
-
2. **分支名声明**:块内必须有一行 `# branch: <分支名>`(冒号前后的空格可灵活)
|
|
325
|
-
3. **任务描述**:块内除分支名行以外的所有行,合并为任务描述(支持多行)
|
|
326
|
-
4. **块外内容忽略**:标签外的任何文本都不会被解析
|
|
327
|
-
5. **必填校验**:每个块必须包含任务描述;分支名默认必填,但使用 `-b` 参数时分支名为可选(会被忽略,用 `-b` 值自动编号)
|
|
328
|
-
|
|
329
|
-
**解析实现:** `src/utils/task-file.ts` 中的 `parseTaskFile()` 和 `loadTaskFile()` 函数,类型定义为 `TaskFileEntry`(`src/types/taskFile.ts`)。
|
|
330
|
-
|
|
331
|
-
#### 任务文件模式运行流程
|
|
332
|
-
|
|
333
|
-
使用 `-f` 时的执行路径(`handleRun` → `handleRunFromFile`):
|
|
334
|
-
|
|
335
|
-
1. 调用 `loadTaskFile(options.file)` 读取解析文件
|
|
336
|
-
2. **有 `-b` 参数**:忽略文件中的分支名,用 `-b` 值自动编号创建 worktree(`createWorktrees(branch, count)`)
|
|
337
|
-
3. **无 `-b` 参数**:使用文件中每个任务的独立分支名,先 `sanitizeBranchName` 清理后调用 `createWorktreesByBranches(branches)`
|
|
338
|
-
4. 调用 `executeBatchTasks(worktrees, tasks, concurrency)` 执行
|
|
339
|
-
|
|
340
|
-
#### --tasks 模式运行流程
|
|
341
|
-
|
|
342
|
-
1. 若传了 `--tasks`,解析得到任务数组 `tasks[]`;若未传,先检测分支是否已存在(已存在则提示使用 `clawt resume -b <branchName>` 恢复会话),然后创建单个 worktree 并启动 Claude Code 交互式界面(流程结束,不进入后续并行执行阶段)
|
|
343
|
-
2. `n = tasks.length`
|
|
344
|
-
3. 按照 **5.1** 的流程创建 `n` 个 worktree
|
|
345
|
-
4. 通过公共函数 `executeBatchTasks`(`src/utils/task-executor.ts`)启动批量任务执行,该函数负责进度面板渲染、SIGINT 中断处理、并发控制和汇总输出。对每个 worktree 并行启动 Claude Code CLI:
|
|
346
|
-
```bash
|
|
347
|
-
cd ~/.clawt/worktrees/<project>/<branchName>-<i>
|
|
348
|
-
claude -p "<tasks[i]>" --output-format stream-json --verbose --permission-mode bypassPermissions
|
|
325
|
+
1. **不兼容旧版本**:本次重构不考虑旧版本数据、旧版本创建的 worktree 或旧版本配置的兼容性。所有命令均假定验证分支和项目级配置已按新架构存在。用户需删除旧 worktree 后重新创建。
|
|
326
|
+
2. **项目级配置前置校验**:仅对 create、run、validate、sync、remove、merge、reset 这 7 个核心命令添加检测,执行时必须先检查项目级配置(`~/.clawt/projects/<projectName>/config.json`)是否存在且包含 `clawtMainWorkBranch`。如果不存在,直接报错退出并提示用户先执行 `clawt init`:
|
|
349
327
|
```
|
|
350
|
-
|
|
351
|
-
5. 进入**事件监听通知**阶段(见 [5.3](#53-任务完成通知机制))
|
|
352
|
-
6. **中断处理(Ctrl+C / SIGINT)**
|
|
353
|
-
- 监听 `SIGINT` 信号,用户按下 Ctrl+C 时触发
|
|
354
|
-
- 向所有正在运行的 Claude Code 子进程发送 `SIGTERM` 终止信号
|
|
355
|
-
- 等待所有子进程退出后,进入清理流程:
|
|
356
|
-
- 如果 `autoDeleteBranch` 为 `true`:自动清理本次创建的所有 worktree 和对应分支
|
|
357
|
-
- 否则:交互式询问用户是否移除刚刚创建的 worktree 和对应分支
|
|
358
|
-
- 用户选择保留时,提示可使用 `clawt remove` 手动清理
|
|
359
|
-
- 清理完成后以退出码 `1` 退出
|
|
360
|
-
|
|
361
|
-
**注意:** 当 `n = 1` 时(只有一个任务),worktree 目录命名规则同 **5.1**(不加 `-1` 后缀)。
|
|
362
|
-
|
|
363
|
-
#### `--dry-run` 预览模式
|
|
364
|
-
|
|
365
|
-
传入 `--dry-run` 时不实际创建 worktree 和执行任务,仅输出预览信息供用户确认。预览由 `printDryRunPreview()`(`src/utils/dry-run.ts`)负责渲染。
|
|
366
|
-
|
|
367
|
-
**输出格式:**
|
|
368
|
-
|
|
369
|
-
```
|
|
370
|
-
════════════════════════════════════════
|
|
371
|
-
Dry Run 预览
|
|
372
|
-
════════════════════════════════════════
|
|
373
|
-
任务数: 3 │ 并发数: 不限制 │ Worktree: ~/.clawt/worktrees/project
|
|
374
|
-
────────────────────────────────────────
|
|
375
|
-
✓ [1/3] feat-login
|
|
376
|
-
路径: ~/.clawt/worktrees/project/feat-login
|
|
377
|
-
任务: 实现登录功能
|
|
378
|
-
|
|
379
|
-
⚠ [2/3] feat-signup — 分支 feat-signup 已存在
|
|
380
|
-
路径: ~/.clawt/worktrees/project/feat-signup
|
|
381
|
-
任务: 实现注册功能
|
|
382
|
-
|
|
383
|
-
✓ [3/3] fix-bug
|
|
384
|
-
路径: ~/.clawt/worktrees/project/fix-bug
|
|
385
|
-
任务: 修复内存泄漏
|
|
386
|
-
|
|
387
|
-
════════════════════════════════════════
|
|
388
|
-
✓ 预览完成,无冲突。移除 --dry-run 即可正式执行。
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
**格式规则:**
|
|
392
|
-
|
|
393
|
-
1. **标题区**:双线分隔符包裹标题 `Dry Run 预览`
|
|
394
|
-
2. **摘要行**:任务数、并发数、Worktree 目录路径合并为一行,用灰色 `│` 分隔;交互式模式(无 `--tasks`)会额外追加模式信息
|
|
395
|
-
3. **分支列表**:
|
|
396
|
-
- 正常分支:行首绿色 `✓` + 序号 + 青色分支名
|
|
397
|
-
- 冲突分支:行首黄色 `⚠` + 序号 + 黄色分支名 + 灰色 `—` + 黄色警告文本(如 `分支 xxx 已存在`),警告合并在序号行
|
|
398
|
-
4. **路径/任务行**:2 空格缩进,灰色标签前缀(`路径:` / `任务:`)
|
|
399
|
-
5. **任务描述截断**:超过 70 字符时末尾加 `...`,多行合并为单行
|
|
400
|
-
6. **结尾**:双线分隔符后根据冲突情况输出结论——无冲突时绿色 `✓` 提示,有冲突时黄色 `⚠` 警告
|
|
401
|
-
|
|
402
|
-
**实现要点:**
|
|
403
|
-
|
|
404
|
-
- 常量定义在 `src/constants/messages/run.ts`(`DRY_RUN_*` 系列)
|
|
405
|
-
- `DRY_RUN_WORKTREE_DIR` 前缀为 `Worktree:`(简短形式)
|
|
406
|
-
- `truncateTaskDesc()` 负责截断任务描述(最大长度 70 字符)
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
|
-
### 5.3 任务完成通知机制
|
|
411
|
-
|
|
412
|
-
**触发条件:** 通过 `clawt run` 启动了多个 Claude Code 任务后自动进入通知模式。
|
|
413
|
-
|
|
414
|
-
**机制说明:**
|
|
415
|
-
|
|
416
|
-
Claude Code CLI 以 `--output-format stream-json --verbose` 运行时,stdout 会持续输出 JSON 行(每行一个事件),包括 `system`、`assistant`(含 `tool_use` 和 `text`)、`user`(含 `tool_result`)等类型。任务结束时输出 `type: "result"` 事件:
|
|
417
|
-
|
|
418
|
-
```json
|
|
419
|
-
{
|
|
420
|
-
"type": "result",
|
|
421
|
-
"subtype": "success",
|
|
422
|
-
"is_error": false,
|
|
423
|
-
"duration_ms": 182809,
|
|
424
|
-
"duration_api_ms": 0,
|
|
425
|
-
"num_turns": 1,
|
|
426
|
-
"result": "xxx",
|
|
427
|
-
"stop_reason": "stop_sequence",
|
|
428
|
-
"session_id": "e771e449-b695-48e7-8006-bbf3f0dd3e98",
|
|
429
|
-
"total_cost_usd": 0,
|
|
430
|
-
"usage": { ... }
|
|
431
|
-
}
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**流式事件解析(`src/utils/stream-parser.ts`):**
|
|
435
|
-
|
|
436
|
-
由于 stdout 的 `data` 事件可能在行中间切割,使用 `createLineBuffer()` 行缓冲器拼接完整行后,通过 `parseStreamLine()` 解析为 `StreamEvent` 对象,再由 `parseStreamEvent()` 提取活动信息(`ParsedActivity`):
|
|
437
|
-
|
|
438
|
-
- **`tool_use` 类型**:提取工具名和文件路径/命令参数,格式如 `Read index.ts`、`Bash ls -la`
|
|
439
|
-
- **`text` 类型**:提取文本片段,格式如 `思考中: 让我分析一下`
|
|
440
|
-
- **`result` 类型**:构造 `ClaudeCodeResult` 对象,提取耗时、费用、结果文本等
|
|
441
|
-
|
|
442
|
-
活动描述文本最大长度为 `ACTIVITY_TEXT_MAX_LENGTH`(30 字符),超出后截断并追加省略号。结果预览文本最大长度为 `RESULT_PREVIEW_MAX_LENGTH`(40 字符)。
|
|
443
|
-
|
|
444
|
-
**事件监听与通知流程:**
|
|
445
|
-
|
|
446
|
-
1. 为每个 Claude Code 子进程维护状态(运行中 / 已完成 / 已失败)
|
|
447
|
-
2. 监听每个子进程的 `close` 事件(基于 Node.js `ChildProcess` 的事件驱动机制)
|
|
448
|
-
3. 当某个子进程触发 `close` 事件时,解析流式输出中最后的 `result` 事件
|
|
449
|
-
4. 在主 worktree 的 clawt 终端实时输出通知。TTY 环境下使用进度面板,进度面板每个任务行第二列显示 worktree 路径(终端可点击跳转),运行中显示实时活动描述,完成/失败后显示结果预览:
|
|
450
|
-
|
|
451
|
-
```
|
|
452
|
-
✓ [完成] worktree: ~/.clawt/worktrees/main-project/feature-scheme-1
|
|
453
|
-
分支: feature-scheme-1
|
|
454
|
-
耗时: 182.8s
|
|
455
|
-
花费: $0.05
|
|
456
|
-
结果: success
|
|
457
|
-
────────────────────────────────────────
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
5. 先完成的先通知,**不需要**失败重试机制
|
|
461
|
-
6. 当所有任务完成后,输出汇总信息:
|
|
462
|
-
|
|
463
|
-
```
|
|
464
|
-
════════════════════════════════════════
|
|
465
|
-
全部任务已完成 (3/3)
|
|
466
|
-
成功: 2
|
|
467
|
-
失败: 1
|
|
468
|
-
总耗时: 245.3s
|
|
469
|
-
总花费: $0.15
|
|
470
|
-
════════════════════════════════════════
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
#### 进度面板渲染机制
|
|
474
|
-
|
|
475
|
-
进度面板由 `ProgressRenderer`(`src/utils/progress.ts`)负责渲染,渲染函数拆分到 `src/utils/progress-render.ts`。
|
|
476
|
-
|
|
477
|
-
**TTY 模式渲染策略(备选屏幕缓冲区):**
|
|
478
|
-
|
|
479
|
-
- **进入备选屏幕**:`start()` 时通过 `ALT_SCREEN_ENTER`(`\x1B[?1049h`)进入终端备选屏幕缓冲区,隔离进度面板与主屏幕内容
|
|
480
|
-
- **禁用行换行**:通过 `LINE_WRAP_DISABLE`(`\x1B[?7l`)防止超长行自动折行,配合按终端宽度截断保证每行只占一行
|
|
481
|
-
- **每帧渲染**:使用 `CLEAR_SCREEN` + `CURSOR_HOME` 清屏后完全重绘,无需计算 `CURSOR_UP` 回退量,不受终端 reflow 影响
|
|
482
|
-
- **防闪烁**:每帧渲染使用 Synchronized Output(`SYNC_OUTPUT_START` / `SYNC_OUTPUT_END`),终端缓冲全部输出后一次性刷新
|
|
483
|
-
- **行宽截断**:通过 `truncateToTerminalWidth()`(`src/utils/progress-render.ts`)将含 ANSI 转义码的字符串截断到终端可见列数,使用 `string-width` 库正确计算中文/emoji 宽度
|
|
484
|
-
- **终端 resize 响应**:监听 `process.stdout` 的 `resize` 事件,窗口宽度变化时立即触发重绘
|
|
485
|
-
- **退出时恢复**:`stop()` 时恢复行换行、显示光标、退出备选屏幕,然后在主屏幕上重新输出最终面板状态(备选屏幕内容不保留)
|
|
486
|
-
- **异常退出兜底**:注册 `process.on('exit')` 处理器,确保即使异常退出也能恢复终端状态
|
|
487
|
-
|
|
488
|
-
**任务行格式:**
|
|
489
|
-
|
|
490
|
-
```
|
|
491
|
-
[1/3] /path/to/worktree ⠹ 运行中 1m23s Read index.ts
|
|
492
|
-
[2/3] /path/to/worktree ✓ 完成 2m05s $0.08 任务已成功完成
|
|
493
|
-
[3/3] /path/to/worktree ● 排队中
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
- 第二列为 worktree 路径(`path.padEnd(maxPathWidth)` 对齐)
|
|
497
|
-
- 运行中状态:末尾显示实时活动描述文本(如工具名+文件名、思考中+文本片段)
|
|
498
|
-
- 完成/失败状态:末尾显示结果预览文本(从 `ClaudeCodeResult.result` 提取,最大 40 字符)
|
|
499
|
-
|
|
500
|
-
**非 TTY 降级模式:**
|
|
501
|
-
|
|
502
|
-
- 启动时输出 `[1/3] branch 启动 path`
|
|
503
|
-
- 完成时输出 `[1/3] branch ✓ 完成 duration cost detail`(`detail` 优先使用结果预览,无则回退到路径)
|
|
504
|
-
- 失败时输出 `[1/3] branch ✗ 失败 duration detail`
|
|
505
|
-
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
### 5.4 在主 Worktree 验证其他分支
|
|
509
|
-
|
|
510
|
-
**命令:**
|
|
511
|
-
|
|
512
|
-
```bash
|
|
513
|
-
# 指定分支名(支持模糊匹配)
|
|
514
|
-
clawt validate -b <branchName> [--clean] [-r <command>]
|
|
515
|
-
|
|
516
|
-
# 不指定分支名(列出所有分支供选择)
|
|
517
|
-
clawt validate [--clean] [-r <command>]
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
**参数:**
|
|
521
|
-
|
|
522
|
-
| 参数 | 必填 | 说明 |
|
|
523
|
-
| ------------- | ---- | ------------------------------------------------------------------------ |
|
|
524
|
-
| `-b` | 否 | 要验证的 worktree 分支名(支持模糊匹配,不传则列出所有分支供选择) |
|
|
525
|
-
| `--clean` | 否 | 清理 validate 状态(重置主 worktree 并删除快照) |
|
|
526
|
-
| `-r, --run` | 否 | validate 成功后在主 worktree 中执行的命令(如测试、构建等) |
|
|
527
|
-
|
|
528
|
-
> **限制:** 单次只能验证一个分支,不支持批量验证。
|
|
529
|
-
|
|
530
|
-
**背景说明:**
|
|
531
|
-
|
|
532
|
-
Git worktree 不会包含 `node_modules`、`.venv` 等依赖文件,每次安装依赖耗时较长。利用 `git diff HEAD...branch --binary`(三点 diff)可以获取目标分支自分叉点以来的全量变更(包含已提交和未提交的修改),将其作为 patch 应用到主 worktree 中进行测试,无需重新安装依赖。
|
|
533
|
-
|
|
534
|
-
**快照机制:**
|
|
535
|
-
|
|
536
|
-
validate 命令引入了**快照(snapshot)机制**来支持增量对比。每次 validate 执行成功后,会将当前全量变更通过 `git write-tree` 保存为 git tree 对象,并将 tree hash 记录到文件(`~/.clawt/validate-snapshots/<project>/<branchName>.tree`),同时将主 worktree 的 HEAD commit hash 记录到文件(`~/.clawt/validate-snapshots/<project>/<branchName>.head`),用于增量 validate 时对齐基准。当再次执行 validate 时,如果主分支 HEAD 未变化,通过 `git read-tree` 将上次快照的 tree 对象载入暂存区;如果主分支 HEAD 已变化(如合并了其他分支),则将旧变更 patch(旧 tree 相对于旧 HEAD 的差异)重放到当前 HEAD 暂存区上,避免新旧 tree 基准不同导致 diff 混入 HEAD 变化的内容。最终用户可通过 `git diff` 查看两次 validate 之间的增量差异。
|
|
537
|
-
|
|
538
|
-
**运行流程:**
|
|
539
|
-
|
|
540
|
-
#### `--clean` 模式
|
|
541
|
-
|
|
542
|
-
当指定 `--clean` 选项时,执行清理逻辑后直接返回,不进入常规 validate 流程:
|
|
543
|
-
|
|
544
|
-
1. **主 worktree 校验** (2.1)
|
|
545
|
-
2. **解析目标 worktree**:通过模糊匹配解析目标分支(匹配策略同下文常规 validate 流程中的描述)
|
|
546
|
-
3. 如果配置项 `confirmDestructiveOps` 为 `true`,提示确认(显示即将执行的危险指令和操作后果),用户取消则退出
|
|
547
|
-
4. 如果主 worktree 有未提交更改,执行 `git reset --hard` + `git clean -fd` 清空
|
|
548
|
-
5. 删除对应分支的快照文件
|
|
549
|
-
6. 输出清理成功提示
|
|
550
|
-
|
|
551
|
-
#### 首次 validate(无历史快照)
|
|
552
|
-
|
|
553
|
-
##### 步骤 0:解析目标 worktree
|
|
554
|
-
|
|
555
|
-
根据 `-b` 参数解析目标 worktree,匹配策略如下:
|
|
556
|
-
|
|
557
|
-
- **未传 `-b` 参数**:
|
|
558
|
-
- 获取当前项目所有 worktree
|
|
559
|
-
- 无可用 worktree → 报错退出
|
|
560
|
-
- 仅 1 个 worktree → 直接使用,无需选择
|
|
561
|
-
- 多个 worktree → 通过交互式列表(Enquirer.Select)让用户选择
|
|
562
|
-
- **传了 `-b` 参数**:
|
|
563
|
-
1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
|
|
564
|
-
2. **模糊匹配**(子串匹配,大小写不敏感):
|
|
565
|
-
- 唯一匹配 → 直接使用
|
|
566
|
-
- 多个匹配 → 通过交互式列表让用户从匹配结果中选择
|
|
567
|
-
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
568
|
-
|
|
569
|
-
##### 步骤 1:检测主 worktree 工作区状态
|
|
570
|
-
|
|
571
|
-
执行 `git status --porcelain`,判断主 worktree 是否有未提交的更改。
|
|
572
|
-
|
|
573
|
-
- **无更改** → 进入步骤 2
|
|
574
|
-
- **有更改** → 提示用户选择处理方式,使用交互式选择(方向键切换,回车确认):
|
|
575
|
-
|
|
576
|
-
```
|
|
577
|
-
⚠ 主 worktree 当前分支有未提交的更改,请选择处理方式:
|
|
578
|
-
|
|
579
|
-
❯ reset (推荐) - 丢弃所有更改 (git reset --hard HEAD && git clean -fd)
|
|
580
|
-
stash - 暂存更改 (git add . && git stash)
|
|
581
|
-
exit - 退出,手动处理
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
| 选项 | 执行命令 | 默认 |
|
|
585
|
-
| ------- | ----------------------------------------- | ---- |
|
|
586
|
-
| `reset` | `git reset --hard HEAD && git clean -fd` | 是 |
|
|
587
|
-
| `stash` | `git add . && git stash` | 否 |
|
|
588
|
-
| `exit` | 退出程序 | 否 |
|
|
589
|
-
|
|
590
|
-
执行完毕后,通过 `git status --porcelain` 再次检测状态,确保工作区干净。如果仍然不干净,报错退出。
|
|
591
|
-
|
|
592
|
-
##### 步骤 2:检测目标分支变更
|
|
593
|
-
|
|
594
|
-
统一检测目标 worktree 的未提交修改和已提交 commit:
|
|
595
|
-
|
|
596
|
-
```bash
|
|
597
|
-
# 检测未提交修改
|
|
598
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
599
|
-
git status --porcelain
|
|
600
|
-
|
|
601
|
-
# 检测已提交 commit(在主 worktree 中执行)
|
|
602
|
-
cd <主 worktree 路径>
|
|
603
|
-
git log HEAD..<branchName> --oneline
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
- **两者均无** → 输出提示 `该 worktree 的分支上没有任何更改,无需验证`,退出
|
|
607
|
-
- **至少有一项** → 继续
|
|
608
|
-
|
|
609
|
-
##### 步骤 3:通过 patch 迁移目标分支全量变更
|
|
610
|
-
|
|
611
|
-
使用三点 diff(`git diff HEAD...branchName --binary`)获取目标分支自分叉点以来的全量变更。如果目标 worktree 有未提交修改,先做临时 commit 以便 diff 能捕获全部变更,diff 完成后撤销临时 commit 恢复原状。
|
|
612
|
-
|
|
613
|
-
```bash
|
|
614
|
-
# 如果有未提交修改,先临时提交
|
|
615
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
616
|
-
git add .
|
|
617
|
-
git commit -m "clawt:temp-commit-for-validate"
|
|
618
|
-
|
|
619
|
-
# 在主 worktree 中执行三点 diff
|
|
620
|
-
cd <主 worktree 路径>
|
|
621
|
-
git diff HEAD...<branchName> --binary | git apply
|
|
622
|
-
|
|
623
|
-
# 撤销临时 commit,恢复目标 worktree 原状
|
|
624
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
625
|
-
git reset --soft HEAD~1
|
|
626
|
-
git restore --staged .
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
> 此步骤结束后,目标 worktree 的代码保持原样,主 worktree 工作目录包含目标分支的全量变更。
|
|
630
|
-
> 如果 patch apply 失败(目标分支与主分支差异过大),`migrateChangesViaPatch` 返回 `{ success: false }`,进入自动 sync 交互流程(见下文 [patch apply 失败后的自动 sync 流程](#patch-apply-失败后的自动-sync-流程))。
|
|
631
|
-
|
|
632
|
-
##### patch apply 失败后的自动 sync 流程
|
|
633
|
-
|
|
634
|
-
当 patch apply 失败时,validate 不再直接退出,而是通过 `handlePatchApplyFailure()` 函数进入交互流程:
|
|
635
|
-
|
|
636
|
-
1. **询问用户**:提示 `是否立即执行 sync 同步主分支到 <branchName>?`
|
|
637
|
-
2. **用户拒绝** → 输出提示 `请手动执行 clawt sync -b <branchName> 同步主分支后重试`,退出
|
|
638
|
-
3. **用户确认** → 调用 `executeSyncForBranch(targetWorktreePath, branchName)` 自动执行 sync
|
|
639
|
-
- **sync 成功** → validate 流程结束(用户需重新执行 validate)
|
|
640
|
-
- **sync 存在冲突** → 输出提示 `同步存在冲突,请进入目标 worktree 手动解决冲突后重试`,退出
|
|
641
|
-
|
|
642
|
-
> `executeSyncForBranch` 为 sync 命令抽取的核心操作函数(见 [5.12](#512-将主分支代码同步到目标-worktree)),供 validate 等命令复用。
|
|
643
|
-
|
|
644
|
-
**实现要点:**
|
|
645
|
-
|
|
646
|
-
- `migrateChangesViaPatch()` 返回类型从 `void` 改为 `{ success: boolean }`,patch apply 失败时返回 `{ success: false }` 而非抛出异常
|
|
647
|
-
- `handleFirstValidate()` 和 `handleIncrementalValidate()` 从同步函数改为 `async` 函数,以支持交互式确认
|
|
648
|
-
- `handlePatchApplyFailure()` 为新增的异步函数(`src/commands/validate.ts`),负责 patch 失败后的交互逻辑
|
|
649
|
-
- 消息常量:`MESSAGES.VALIDATE_CONFIRM_AUTO_SYNC`、`MESSAGES.VALIDATE_AUTO_SYNC_START`、`MESSAGES.VALIDATE_AUTO_SYNC_CONFLICT`、`MESSAGES.VALIDATE_AUTO_SYNC_DECLINED`(`src/constants/messages/validate.ts`)
|
|
650
|
-
|
|
651
|
-
##### 步骤 4:保存快照为 git tree 对象
|
|
652
|
-
|
|
653
|
-
将主 worktree 工作目录的全量变更保存为 git tree 对象,同时记录当前 HEAD commit hash:
|
|
654
|
-
|
|
655
|
-
```bash
|
|
656
|
-
git add .
|
|
657
|
-
git write-tree # → 返回 tree hash,写入 ~/.clawt/validate-snapshots/<project>/<branchName>.tree
|
|
658
|
-
git rev-parse HEAD # → 返回 HEAD commit hash,写入 ~/.clawt/validate-snapshots/<project>/<branchName>.head
|
|
659
|
-
git restore --staged .
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
> 结果:暂存区=空,工作目录=全量变更。
|
|
663
|
-
|
|
664
|
-
##### 步骤 5:输出成功提示
|
|
665
|
-
|
|
666
|
-
```
|
|
667
|
-
✓ 已将分支 feature-scheme-1 的变更应用到主 worktree
|
|
668
|
-
可以开始验证了
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
##### 步骤 6:执行 `--run` 命令(可选)
|
|
672
|
-
|
|
673
|
-
如果用户传入了 `-r, --run` 选项,在 validate 成功后自动在主 worktree 中执行指定命令:
|
|
674
|
-
|
|
675
|
-
```bash
|
|
676
|
-
# 示例:单命令
|
|
677
|
-
clawt validate -b feature-scheme-1 -r "npm test"
|
|
678
|
-
|
|
679
|
-
# 示例:并行执行多个命令(& 为并行分隔符)
|
|
680
|
-
clawt validate -b feature-scheme-1 -r "pnpm test & pnpm build"
|
|
681
|
-
```
|
|
682
|
-
|
|
683
|
-
**执行说明:**
|
|
684
|
-
|
|
685
|
-
- 命令执行失败(退出码非 0 或进程启动失败)**不影响** validate 本身的结果,仅输出提示信息
|
|
686
|
-
- `--clean` 模式下传入 `--run` 会被忽略(只执行 clean 逻辑)
|
|
687
|
-
|
|
688
|
-
**命令解析规则:**
|
|
689
|
-
|
|
690
|
-
`-r` 选项支持通过 `&` 将多个命令并行执行。解析由 `parseParallelCommands()`(`src/utils/shell.ts`)负责:
|
|
691
|
-
|
|
692
|
-
1. 先将命令字符串中的 `&&` 临时替换为占位符,避免被误拆
|
|
693
|
-
2. 按单个 `&` 分割为多个独立命令
|
|
694
|
-
3. 还原占位符为 `&&`,去除首尾空白,过滤空串
|
|
695
|
-
|
|
696
|
-
| 输入示例 | 解析结果 | 执行方式 |
|
|
697
|
-
| -------- | -------- | -------- |
|
|
698
|
-
| `"npm test"` | `["npm test"]` | 单命令,同步执行(`spawnSync` + `inherit`) |
|
|
699
|
-
| `"npm lint && npm test"` | `["npm lint && npm test"]` | 单命令(`&&` 不拆分),同步执行 |
|
|
700
|
-
| `"npm test & npm build"` | `["npm test", "npm build"]` | 并行执行(`spawn` + `Promise.all`) |
|
|
701
|
-
| `"npm lint && npm test & npm build"` | `["npm lint && npm test", "npm build"]` | 并行执行 2 个命令 |
|
|
702
|
-
|
|
703
|
-
**单命令执行:**
|
|
704
|
-
|
|
705
|
-
当解析后只有 1 个命令时,通过 `spawnSync` + `inherit` stdio 模式同步执行,输出实时显示在终端。
|
|
706
|
-
|
|
707
|
-
**并行命令执行:**
|
|
708
|
-
|
|
709
|
-
当解析后有多个命令时,通过 `runParallelCommands()`(`src/utils/shell.ts`)执行:
|
|
710
|
-
|
|
711
|
-
- 每个命令通过 Node.js `spawn` 以 shell 模式启动,`stdio: 'inherit'`
|
|
712
|
-
- 使用 `Promise.all` 等待全部命令完成
|
|
713
|
-
- 完成后汇总输出各命令的执行结果
|
|
714
|
-
|
|
715
|
-
**向后兼容性:**
|
|
716
|
-
|
|
717
|
-
- `-r "npm test"` — 单命令,走原有同步路径,行为无变化
|
|
718
|
-
- `-r "npm lint && npm test"` — `&&` 不拆分,走原有同步路径,行为无变化
|
|
719
|
-
- `-r "npm test & npm build"` — **新行为**:并行执行,等全部完成后汇总
|
|
720
|
-
|
|
721
|
-
**输出格式:**
|
|
722
|
-
|
|
723
|
-
```
|
|
724
|
-
# 单命令执行成功
|
|
725
|
-
正在主 worktree 中执行命令: npm test
|
|
726
|
-
────────────────────────────────────────
|
|
727
|
-
... 命令的实时输出 ...
|
|
728
|
-
────────────────────────────────────────
|
|
729
|
-
✓ 命令执行完成: npm test,退出码: 0
|
|
730
|
-
|
|
731
|
-
# 单命令执行失败(退出码非 0)
|
|
732
|
-
正在主 worktree 中执行命令: npm test
|
|
733
|
-
────────────────────────────────────────
|
|
734
|
-
... 命令的实时输出 ...
|
|
735
|
-
────────────────────────────────────────
|
|
736
|
-
✗ 命令执行完成: npm test,退出码: 1
|
|
737
|
-
|
|
738
|
-
# 单命令执行出错(进程启动失败)
|
|
739
|
-
正在主 worktree 中执行命令: nonexistent
|
|
740
|
-
────────────────────────────────────────
|
|
741
|
-
────────────────────────────────────────
|
|
742
|
-
✗ 命令执行出错: spawn ENOENT
|
|
743
|
-
|
|
744
|
-
# 并行命令执行(全部成功)
|
|
745
|
-
正在并行执行 2 个命令...
|
|
746
|
-
[1/2] pnpm test
|
|
747
|
-
[2/2] pnpm build
|
|
748
|
-
────────────────────────────────────────
|
|
749
|
-
... 各命令的实时输出(交错显示) ...
|
|
750
|
-
────────────────────────────────────────
|
|
751
|
-
✓ pnpm test
|
|
752
|
-
✓ pnpm build
|
|
753
|
-
✓ 全部 2 个命令执行成功
|
|
754
|
-
|
|
755
|
-
# 并行命令执行(部分失败)
|
|
756
|
-
正在并行执行 2 个命令...
|
|
757
|
-
[1/2] pnpm test
|
|
758
|
-
[2/2] pnpm build
|
|
759
|
-
────────────────────────────────────────
|
|
760
|
-
... 各命令的实时输出(交错显示) ...
|
|
761
|
-
────────────────────────────────────────
|
|
762
|
-
✗ pnpm test(退出码: 1)
|
|
763
|
-
✓ pnpm build
|
|
764
|
-
共 2 个命令,1 个成功,1 个失败
|
|
765
|
-
```
|
|
766
|
-
|
|
767
|
-
**实现要点:**
|
|
768
|
-
|
|
769
|
-
- 命令解析:`parseParallelCommands()`(`src/utils/shell.ts`)
|
|
770
|
-
- 并行执行:`runParallelCommands()`(`src/utils/shell.ts`),返回 `ParallelCommandResult[]`
|
|
771
|
-
- 结果汇总:`reportParallelResults()`(`src/commands/validate.ts`)
|
|
772
|
-
- 消息常量:`MESSAGES.VALIDATE_PARALLEL_*` 系列(`src/constants/messages/validate.ts`)
|
|
773
|
-
|
|
774
|
-
#### 增量 validate(存在历史快照)
|
|
775
|
-
|
|
776
|
-
当 `~/.clawt/validate-snapshots/<project>/<branchName>.tree` 存在时,自动进入增量模式:
|
|
777
|
-
|
|
778
|
-
##### 步骤 1:读取旧快照
|
|
779
|
-
|
|
780
|
-
在清空主 worktree 之前,读取上次保存的快照 tree hash 及当时的 HEAD commit hash。
|
|
781
|
-
|
|
782
|
-
##### 步骤 2:确保主 worktree 干净
|
|
783
|
-
|
|
784
|
-
如果主 worktree 有残留状态,让用户选择处理方式(同首次 validate 步骤 1 的交互),做兜底清理。
|
|
785
|
-
|
|
786
|
-
##### 步骤 3:从目标分支获取最新全量变更
|
|
787
|
-
|
|
788
|
-
通过 patch 方式从目标分支获取最新全量变更(流程同首次 validate 的步骤 3)。如果 patch apply 失败,同样进入自动 sync 交互流程(见首次 validate 的 [patch apply 失败后的自动 sync 流程](#patch-apply-失败后的自动-sync-流程)),validate 流程提前结束。
|
|
789
|
-
|
|
790
|
-
##### 步骤 4:保存最新快照为 git tree 对象
|
|
791
|
-
|
|
792
|
-
将最新全量变更保存为新的 tree 对象(覆盖旧快照),同时记录当前 HEAD commit hash(流程同首次 validate 的步骤 4)。
|
|
793
|
-
|
|
794
|
-
##### 步骤 5:将旧变更状态载入暂存区
|
|
795
|
-
|
|
796
|
-
根据主分支 HEAD 是否发生变化,选择不同的策略将旧变更载入暂存区:
|
|
797
|
-
|
|
798
|
-
**情况 A:HEAD 未变化(或旧版快照无 HEAD 信息)**
|
|
799
|
-
|
|
800
|
-
直接通过 `git read-tree` 将旧 tree 对象载入暂存区:
|
|
801
|
-
|
|
802
|
-
```bash
|
|
803
|
-
git read-tree <旧 tree hash>
|
|
804
|
-
```
|
|
805
|
-
|
|
806
|
-
- **读取成功** → 结果:暂存区=上次快照,工作目录=最新全量变更(用户可通过 `git diff` 查看增量差异)
|
|
807
|
-
- **读取失败**(tree 对象可能被 git gc 回收)→ 降级为全量模式,暂存区保持为空,等同于首次 validate 的结果
|
|
808
|
-
|
|
809
|
-
**情况 B:HEAD 发生了变化(如主分支合并了其他分支)**
|
|
810
|
-
|
|
811
|
-
此时旧 tree 对象基于旧 HEAD,直接 read-tree 会导致 diff 混入 HEAD 变化的内容。需要将旧变更 patch(旧 tree 相对于旧 HEAD 的差异)重放到当前 HEAD 暂存区上:
|
|
812
|
-
|
|
813
|
-
```bash
|
|
814
|
-
# 获取旧 HEAD 对应的 tree hash
|
|
815
|
-
git rev-parse <旧 HEAD commit hash>^{tree} # → 旧 HEAD tree hash
|
|
816
|
-
|
|
817
|
-
# 提取旧变更 patch(旧 HEAD tree → 旧快照 tree 的差异)
|
|
818
|
-
git diff-tree -p --binary <旧 HEAD tree hash> <旧快照 tree hash>
|
|
819
|
-
|
|
820
|
-
# 检测 patch 能否无冲突地应用到暂存区
|
|
821
|
-
git apply --cached --check < patch
|
|
822
|
-
|
|
823
|
-
# 无冲突:apply --cached 到当前 HEAD 暂存区
|
|
824
|
-
git apply --cached < patch
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
- **patch 为空**(旧变更为空)→ 暂存区保持干净
|
|
828
|
-
- **无冲突** → apply --cached 到当前 HEAD 暂存区,结果与情况 A 一致
|
|
829
|
-
- **有冲突** → 降级为全量模式(暂存区保持为空),等同于首次 validate 的结果
|
|
830
|
-
|
|
831
|
-
##### 步骤 6:输出成功提示
|
|
832
|
-
|
|
833
|
-
```
|
|
834
|
-
# 增量模式成功
|
|
835
|
-
✓ 已将分支 feature-scheme-1 的最新变更应用到主 worktree(增量模式)
|
|
836
|
-
暂存区 = 上次快照,工作目录 = 最新变更
|
|
837
|
-
|
|
838
|
-
# 增量降级为全量
|
|
839
|
-
✓ 已将分支 feature-scheme-1 的变更应用到主 worktree
|
|
840
|
-
可以开始验证了
|
|
841
|
-
```
|
|
842
|
-
|
|
843
|
-
##### 步骤 7:执行 `--run` 命令(可选)
|
|
844
|
-
|
|
845
|
-
与首次 validate 的步骤 6 相同,增量 validate 成功后也会执行 `-r, --run` 指定的命令。
|
|
846
|
-
|
|
847
|
-
---
|
|
848
|
-
|
|
849
|
-
### 5.5 移除 Worktree
|
|
850
|
-
|
|
851
|
-
**命令:**
|
|
852
|
-
|
|
853
|
-
```bash
|
|
854
|
-
# 移除当前项目所有 worktree
|
|
855
|
-
clawt remove --all
|
|
856
|
-
|
|
857
|
-
# 指定分支名(支持模糊匹配)
|
|
858
|
-
clawt remove -b <branchName>
|
|
859
|
-
|
|
860
|
-
# 不指定参数(列出所有分支供多选)
|
|
861
|
-
clawt remove
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
**参数:**
|
|
865
|
-
|
|
866
|
-
| 参数 | 必填 | 说明 |
|
|
867
|
-
| --------- | ---- | ---------------------------------------------------------------------- |
|
|
868
|
-
| `--all` | 否 | 移除当前项目 (`~/.clawt/worktrees/<project>/`) 下所有 worktree |
|
|
869
|
-
| `-b` | 否 | 指定分支名(支持模糊匹配,不传则列出所有分支供多选) |
|
|
870
|
-
|
|
871
|
-
> **提示:** 不传 `--all` 也不传 `-b` 时,会列出当前项目所有 worktree 供交互式多选。
|
|
872
|
-
|
|
873
|
-
**运行流程:**
|
|
874
|
-
|
|
875
|
-
1. **主 worktree 校验** (2.1)
|
|
876
|
-
2. **获取项目名** (2.2)
|
|
877
|
-
3. **确定待移除的 worktree 列表**:
|
|
878
|
-
- **指定 `--all`** → 选中当前项目所有 worktree
|
|
879
|
-
- **未指定 `--all`** → 通过 `resolveTargetWorktrees` 解析目标 worktree(多选版本),匹配策略如下:
|
|
880
|
-
- **未传 `-b` 参数**:
|
|
881
|
-
- 无可用 worktree → 报错退出
|
|
882
|
-
- 仅 1 个 worktree → 直接使用,无需选择
|
|
883
|
-
- 多个 worktree → 通过交互式多选列表(Enquirer.MultiSelect)让用户选择(空格选择,回车确认)
|
|
884
|
-
- **传了 `-b` 参数**:
|
|
885
|
-
1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
|
|
886
|
-
2. **模糊匹配**(子串匹配,大小写不敏感):
|
|
887
|
-
- 唯一匹配 → 直接使用
|
|
888
|
-
- 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
|
|
889
|
-
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
890
|
-
4. 列出即将移除的 worktree 及对应分支:
|
|
891
|
-
|
|
892
|
-
```
|
|
893
|
-
即将移除以下 worktree 及本地分支:
|
|
894
|
-
|
|
895
|
-
1. ~/.clawt/worktrees/main-project/feature-scheme-1 → 分支: feature-scheme-1
|
|
896
|
-
2. ~/.clawt/worktrees/main-project/feature-scheme-2 → 分支: feature-scheme-2
|
|
897
|
-
3. ~/.clawt/worktrees/main-project/feature-scheme-3 → 分支: feature-scheme-3
|
|
898
|
-
|
|
899
|
-
是否同时删除对应的本地分支?(y/N)
|
|
900
|
-
```
|
|
901
|
-
|
|
902
|
-
5. 用户确认后(只需确认一次),依次执行:
|
|
903
|
-
|
|
904
|
-
```bash
|
|
905
|
-
# 移除 worktree
|
|
906
|
-
git worktree remove -f <worktree路径>
|
|
907
|
-
|
|
908
|
-
# 如果用户选择了删除分支
|
|
909
|
-
git branch -D <branchName>
|
|
910
|
-
|
|
911
|
-
# 清理该分支对应的 validate 快照
|
|
912
|
-
```
|
|
913
|
-
|
|
914
|
-
6. 如果配置文件 `~/.clawt/config.json` 中 `autoDeleteBranch` 为 `true`,则跳过询问,直接删除分支。
|
|
915
|
-
|
|
916
|
-
7. 如果使用 `--all` 模式,额外清理整个项目的 validate 快照目录。
|
|
917
|
-
|
|
918
|
-
8. 移除完成后,清理空目录(如果 `~/.clawt/worktrees/<project>/` 下已无 worktree,则删除该项目目录)。
|
|
919
|
-
|
|
920
|
-
9. 批量移除时,单个 worktree 移除失败不会中断整个流程,而是收集所有失败项,最后汇总报告。
|
|
921
|
-
|
|
922
|
-
---
|
|
923
|
-
|
|
924
|
-
### 5.6 合并验证过的分支
|
|
925
|
-
|
|
926
|
-
**命令:**
|
|
927
|
-
|
|
928
|
-
```bash
|
|
929
|
-
# 指定分支名(支持模糊匹配)
|
|
930
|
-
clawt merge -b <branchName> [-m <commitMessage>]
|
|
931
|
-
|
|
932
|
-
# 不指定分支名(列出所有分支供选择)
|
|
933
|
-
clawt merge [-m <commitMessage>]
|
|
934
|
-
```
|
|
935
|
-
|
|
936
|
-
**参数:**
|
|
937
|
-
|
|
938
|
-
| 参数 | 必填 | 说明 |
|
|
939
|
-
| ---- | ---- | ------------------------------------------------------------------------ |
|
|
940
|
-
| `-b` | 否 | 要合并的分支名(支持模糊匹配,不传则列出所有分支供选择) |
|
|
941
|
-
| `-m` | 否 | 提交信息(目标 worktree 工作区有修改时必填) |
|
|
942
|
-
|
|
943
|
-
**运行流程:**
|
|
944
|
-
|
|
945
|
-
1. **主 worktree 校验** (2.1)
|
|
946
|
-
2. **解析目标 worktree**:根据 `-b` 参数解析目标 worktree,匹配策略如下:
|
|
947
|
-
- **未传 `-b` 参数**:
|
|
948
|
-
- 获取当前项目所有 worktree
|
|
949
|
-
- 无可用 worktree → 报错退出
|
|
950
|
-
- 仅 1 个 worktree → 直接使用,无需选择
|
|
951
|
-
- 多个 worktree → 通过交互式列表(Enquirer.Select)让用户选择
|
|
952
|
-
- **传了 `-b` 参数**:
|
|
953
|
-
1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
|
|
954
|
-
2. **模糊匹配**(子串匹配,大小写不敏感):
|
|
955
|
-
- 唯一匹配 → 直接使用
|
|
956
|
-
- 多个匹配 → 通过交互式列表让用户从匹配结果中选择
|
|
957
|
-
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
958
|
-
3. **主 worktree 状态检测**
|
|
959
|
-
- 执行 `git status --porcelain`
|
|
960
|
-
- 如果有更改:
|
|
961
|
-
- 如果存在该分支的 validate 快照(`~/.clawt/validate-snapshots/<project>/<branchName>.tree`),额外输出警告提示用户可先执行 `clawt validate -b <branchName> --clean` 清理
|
|
962
|
-
- 提示 `主 worktree 有未提交的更改,请先处理`,退出
|
|
963
|
-
- 无更改 → 继续
|
|
964
|
-
4. **Squash 检测与执行(auto-save 临时提交压缩)**
|
|
965
|
-
- 通过 `git log HEAD..<branchName> --format=%s` 检查目标分支是否存在以 `AUTO_SAVE_COMMIT_MESSAGE`(`chore: auto-save before sync`)为前缀的 commit
|
|
966
|
-
- **不存在** → 跳过,进入步骤 5
|
|
967
|
-
- **存在** → 提示用户是否将所有提交压缩为一个:
|
|
968
|
-
```
|
|
969
|
-
检测到 sync 产生的临时提交,是否将所有提交压缩为一个?
|
|
970
|
-
压缩后变更将保留在目标worktree的暂存区,需要重新提交
|
|
971
|
-
```
|
|
972
|
-
- **用户选择不压缩** → 跳过,进入步骤 5
|
|
973
|
-
- **用户选择压缩** →
|
|
974
|
-
1. 获取主分支名(`git rev-parse --abbrev-ref HEAD`)
|
|
975
|
-
2. 计算分叉点:`git merge-base <mainBranch> <branchName>`
|
|
976
|
-
3. 在目标 worktree 中执行 `git reset --soft <merge-base>`,将所有 commit 撤销到暂存区
|
|
977
|
-
4. 如果用户提供了 `-m` → 直接在目标 worktree 执行 `git commit -m '<commitMessage>'`,输出成功提示,继续步骤 5
|
|
978
|
-
5. 如果用户未提供 `-m` → 提示用户前往目标 worktree 自行提交后重新执行 `clawt merge`,**退出流程**
|
|
979
|
-
5. **根据目标 worktree 状态决定是否需要提交**
|
|
980
|
-
- 检测目标 worktree 工作区是否干净(`git status --porcelain`)
|
|
981
|
-
- **工作区有未提交修改**:
|
|
982
|
-
- 如果用户未提供 `-m`,提示 `<worktreePath> 有未提交的修改,请通过 -m 参数提供提交信息`(其中 `<worktreePath>` 为目标 worktree 的完整路径),退出
|
|
983
|
-
- 提供了 `-m` → 执行提交:
|
|
984
|
-
```bash
|
|
985
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
986
|
-
git add .
|
|
987
|
-
git commit -m '<commitMessage>'
|
|
988
|
-
```
|
|
989
|
-
- **工作区干净**:
|
|
990
|
-
- 检查目标分支相对于主分支是否有本地提交(`git log HEAD..<branchName> --oneline`)
|
|
991
|
-
- 有本地提交 → 跳过提交步骤,直接进入合并
|
|
992
|
-
- 无本地提交 → 提示 `目标 worktree 没有任何可合并的变更(工作区干净且无本地提交)`,退出
|
|
993
|
-
6. **回到主 worktree 进行合并**
|
|
994
|
-
```bash
|
|
995
|
-
cd <主 worktree 路径>
|
|
996
|
-
git merge <branchName>
|
|
997
|
-
```
|
|
998
|
-
7. **冲突检测**
|
|
999
|
-
- 检查 merge 退出码及 `git status` 是否存在冲突
|
|
1000
|
-
- **有冲突** → 提示 `合并存在冲突,请手动处理`,退出
|
|
1001
|
-
- **无冲突** → 继续
|
|
1002
|
-
8. **推送(受 `autoPullPush` 配置控制)**
|
|
1003
|
-
```bash
|
|
1004
|
-
# 仅当 autoPullPush 为 true 时执行
|
|
1005
|
-
git pull
|
|
1006
|
-
git push
|
|
1007
|
-
```
|
|
1008
|
-
9. **输出成功提示**
|
|
1009
|
-
|
|
1010
|
-
```
|
|
1011
|
-
# 提供了 -m 且已推送时
|
|
1012
|
-
✓ 分支 feature-scheme-1 已成功合并到当前分支
|
|
1013
|
-
提交信息: <commitMessage>
|
|
1014
|
-
已推送到远程仓库
|
|
1015
|
-
|
|
1016
|
-
# 提供了 -m 但未推送时
|
|
1017
|
-
✓ 分支 feature-scheme-1 已成功合并到当前分支
|
|
1018
|
-
提交信息: <commitMessage>
|
|
1019
|
-
|
|
1020
|
-
# 未提供 -m 且已推送时
|
|
1021
|
-
✓ 分支 feature-scheme-1 已成功合并到当前分支
|
|
1022
|
-
已推送到远程仓库
|
|
1023
|
-
|
|
1024
|
-
# 未提供 -m 且未推送时
|
|
1025
|
-
✓ 分支 feature-scheme-1 已成功合并到当前分支
|
|
1026
|
-
```
|
|
1027
|
-
|
|
1028
|
-
10. **merge 成功后确认并清理 worktree 和分支(可选)**
|
|
1029
|
-
- 如果配置文件中 `autoDeleteBranch` 为 `true`,自动执行清理
|
|
1030
|
-
- 否则交互式询问用户是否清理
|
|
1031
|
-
- 用户确认后,依次执行:
|
|
1032
|
-
```bash
|
|
1033
|
-
# 移除 worktree
|
|
1034
|
-
git worktree remove -f <worktree路径>
|
|
1035
|
-
# 删除本地分支
|
|
1036
|
-
git branch -D <branchName>
|
|
1037
|
-
# 修剪 worktree 引用
|
|
1038
|
-
git worktree prune
|
|
1039
|
-
# 如果项目 worktree 目录为空,则清理空目录
|
|
1040
|
-
```
|
|
1041
|
-
- 输出清理成功提示:`✓ 已清理 worktree 和分支: <branchName>`
|
|
1042
|
-
|
|
1043
|
-
11. **清理 validate 快照**
|
|
1044
|
-
- merge 成功后,如果存在该分支的 validate 快照(`~/.clawt/validate-snapshots/<project>/<branchName>.tree` 和 `<branchName>.head`),自动删除这些快照文件(merge 成功后快照已无意义)
|
|
1045
|
-
|
|
1046
|
-
> **注意:** 清理确认和清理操作均在 merge 成功后执行。只有 merge 成功才会询问用户是否清理 worktree 和分支,避免 merge 冲突时用户被提前询问造成困惑。
|
|
1047
|
-
|
|
1048
|
-
---
|
|
1049
|
-
|
|
1050
|
-
### 5.7 默认配置文件
|
|
1051
|
-
|
|
1052
|
-
**路径:** `~/.clawt/config.json`
|
|
1053
|
-
|
|
1054
|
-
**生成时机:** 全局安装后自动生成(通过 `postinstall` 脚本)。
|
|
1055
|
-
|
|
1056
|
-
**升级策略:** 配置文件已存在时,执行增量合并而非简单跳过:
|
|
1057
|
-
|
|
1058
|
-
- **新版本新增的配置项** → 使用默认值补充到用户配置中
|
|
1059
|
-
- **用户已有的配置项** → 保留用户的值,不覆盖
|
|
1060
|
-
- **新版本已移除的配置项** → 从用户配置中删除
|
|
1061
|
-
|
|
1062
|
-
仅在合并后配置发生变化时才写入文件。配置文件损坏或无法解析时,视为不存在,重新生成默认配置。
|
|
1063
|
-
|
|
1064
|
-
**默认内容:**
|
|
1065
|
-
|
|
1066
|
-
```json
|
|
1067
|
-
{
|
|
1068
|
-
"autoDeleteBranch": false,
|
|
1069
|
-
"claudeCodeCommand": "claude",
|
|
1070
|
-
"autoPullPush": false,
|
|
1071
|
-
"confirmDestructiveOps": true,
|
|
1072
|
-
"maxConcurrency": 0,
|
|
1073
|
-
"terminalApp": "auto",
|
|
1074
|
-
"aliases": {},
|
|
1075
|
-
"autoUpdate": true
|
|
1076
|
-
}
|
|
1077
|
-
```
|
|
1078
|
-
|
|
1079
|
-
**配置项说明:**
|
|
1080
|
-
|
|
1081
|
-
| 配置项 | 类型 | 默认值 | 说明 |
|
|
1082
|
-
| ------------------ | --------- | --------- | -------------------------------------------------- |
|
|
1083
|
-
| `autoDeleteBranch` | `boolean` | `false` | 移除 worktree 时是否自动删除对应本地分支(无需每次确认);merge 成功后是否自动清理 worktree 和分支;run 任务被中断(Ctrl+C)后是否自动清理本次创建的 worktree 和分支 |
|
|
1084
|
-
| `claudeCodeCommand` | `string` | `"claude"` | Claude Code CLI 启动指令,用于 `clawt run` 不传 `--tasks` 时和 `clawt resume` 在 worktree 中打开交互式界面 |
|
|
1085
|
-
| `autoPullPush` | `boolean` | `false` | merge 成功后是否自动执行 git pull 和 git push |
|
|
1086
|
-
| `confirmDestructiveOps` | `boolean` | `true` | 执行破坏性操作(reset、validate --clean、config reset)前是否提示确认 |
|
|
1087
|
-
| `maxConcurrency` | `number` | `0` | run 命令默认最大并发数,`0` 表示不限制 |
|
|
1088
|
-
| `terminalApp` | `string` | `"auto"` | 批量 resume 使用的终端应用:`auto`(自动检测)、`iterm2`、`terminal`(macOS) |
|
|
1089
|
-
| `aliases` | `Record<string, string>` | `{}` | 命令别名映射,键为别名,值为目标内置命令名 |
|
|
1090
|
-
| `autoUpdate` | `boolean` | `true` | 是否启用自动更新检查(每 24 小时通过 npm registry 检查一次新版本) |
|
|
1091
|
-
|
|
1092
|
-
---
|
|
1093
|
-
|
|
1094
|
-
### 5.8 获取当前项目所有 Worktree
|
|
1095
|
-
|
|
1096
|
-
**命令:**
|
|
1097
|
-
|
|
1098
|
-
```bash
|
|
1099
|
-
clawt list [--json]
|
|
1100
|
-
```
|
|
1101
|
-
|
|
1102
|
-
**参数:**
|
|
1103
|
-
|
|
1104
|
-
| 参数 | 必填 | 说明 |
|
|
1105
|
-
| -------- | ---- | ---------------------------------------- |
|
|
1106
|
-
| `--json` | 否 | 以 JSON 格式输出(仅包含 path 和 branch) |
|
|
1107
|
-
|
|
1108
|
-
**运行流程:**
|
|
1109
|
-
|
|
1110
|
-
1. **主 worktree 校验** (2.1)
|
|
1111
|
-
2. **获取项目名** (2.2)
|
|
1112
|
-
3. 扫描 `~/.clawt/worktrees/<project>/` 目录
|
|
1113
|
-
4. 对每个子目录,验证是否为有效的 git worktree(`git worktree list` 交叉验证)
|
|
1114
|
-
5. 根据 `--json` 选项决定输出格式:
|
|
1115
|
-
- 指定 `--json` → 以 JSON 格式输出
|
|
1116
|
-
- 未指定 → 以文本格式输出
|
|
1117
|
-
|
|
1118
|
-
**文本输出格式(默认):**
|
|
1119
|
-
|
|
1120
|
-
每个 worktree 会显示路径、分支名和变更状态。如果某个 worktree 处于空闲状态(0 个提交、无变更、无未提交修改),其路径会以橙色高亮显示,方便用户快速识别可能需要清理或还未开始工作的 worktree。
|
|
1121
|
-
|
|
1122
|
-
```
|
|
1123
|
-
当前项目: main-project
|
|
1124
|
-
|
|
1125
|
-
~/.clawt/worktrees/main-project/feature-scheme-1 [feature-scheme-1]
|
|
1126
|
-
~/.clawt/worktrees/main-project/feature-scheme-2 [feature-scheme-2]
|
|
1127
|
-
~/.clawt/worktrees/main-project/feature-scheme-3 [feature-scheme-3]
|
|
1128
|
-
~/.clawt/worktrees/main-project/bugfix-login [bugfix-login]
|
|
1129
|
-
|
|
1130
|
-
共 4 个 worktree
|
|
1131
|
-
```
|
|
1132
|
-
|
|
1133
|
-
如果没有 worktree:
|
|
1134
|
-
|
|
1135
|
-
```
|
|
1136
|
-
当前项目: main-project
|
|
1137
|
-
|
|
1138
|
-
(无 worktree)
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
**JSON 输出格式(`--json`):**
|
|
1142
|
-
|
|
1143
|
-
```json
|
|
1144
|
-
{
|
|
1145
|
-
"project": "main-project",
|
|
1146
|
-
"total": 4,
|
|
1147
|
-
"worktrees": [
|
|
1148
|
-
{
|
|
1149
|
-
"path": "~/.clawt/worktrees/main-project/feature-scheme-1",
|
|
1150
|
-
"branch": "feature-scheme-1"
|
|
1151
|
-
},
|
|
1152
|
-
{
|
|
1153
|
-
"path": "~/.clawt/worktrees/main-project/feature-scheme-2",
|
|
1154
|
-
"branch": "feature-scheme-2"
|
|
1155
|
-
}
|
|
1156
|
-
]
|
|
1157
|
-
}
|
|
1158
|
-
```
|
|
1159
|
-
|
|
1160
|
-
---
|
|
1161
|
-
|
|
1162
|
-
### 5.9 日志系统
|
|
1163
|
-
|
|
1164
|
-
**日志目录:** `~/.clawt/logs/`
|
|
1165
|
-
|
|
1166
|
-
**日志文件命名:** `clawt-YYYY-MM-DD.log`(按日期滚动)
|
|
1167
|
-
|
|
1168
|
-
**日志级别:**
|
|
1169
|
-
|
|
1170
|
-
| 级别 | 说明 | 使用场景 |
|
|
1171
|
-
| ------- | ------------------ | -------------------------------------- |
|
|
1172
|
-
| `debug` | 调试信息 | Git 命令执行详情、变量值等 |
|
|
1173
|
-
| `info` | 一般信息 | 操作开始/完成、创建/移除 worktree 等 |
|
|
1174
|
-
| `warn` | 警告信息 | 分支名被转换、非致命异常等 |
|
|
1175
|
-
| `error` | 错误信息 | 命令执行失败、校验不通过等 |
|
|
1176
|
-
|
|
1177
|
-
**实现方案:** 使用 `winston` + `winston-daily-rotate-file` 库。
|
|
1178
|
-
|
|
1179
|
-
**日志格式:**
|
|
1180
|
-
|
|
1181
|
-
```
|
|
1182
|
-
[2025-02-06 14:30:22] [INFO] 创建 worktree: ~/.clawt/worktrees/main-project/feature-scheme-1
|
|
1183
|
-
[2025-02-06 14:30:22] [DEBUG] 执行命令: git worktree add -b feature-scheme-1 ~/.clawt/worktrees/main-project/feature-scheme-1
|
|
1184
|
-
[2025-02-06 14:30:23] [WARN] 分支名已转换: feature/a.b → feature-a-b
|
|
1185
|
-
[2025-02-06 14:30:25] [ERROR] 分支 feature-scheme-1 已存在,无法创建
|
|
1186
|
-
```
|
|
1187
|
-
|
|
1188
|
-
**保留策略:**
|
|
1189
|
-
|
|
1190
|
-
- 日志文件保留 30 天
|
|
1191
|
-
- 单个日志文件最大 10MB
|
|
1192
|
-
|
|
1193
|
-
#### `--debug` 控制台调试输出
|
|
1194
|
-
|
|
1195
|
-
通过全局选项 `--debug` 可将调试日志实时输出到终端,方便排查问题。
|
|
1196
|
-
|
|
1197
|
-
**实现机制:**
|
|
1198
|
-
|
|
1199
|
-
- 在 Commander.js 的 `preAction` 钩子中检测 `--debug` 选项,按需调用 `enableConsoleTransport()` 函数
|
|
1200
|
-
- `enableConsoleTransport()` 动态向 winston 实例添加 `Console` transport(level 为 `debug`),该函数幂等,多次调用不会重复添加 transport
|
|
1201
|
-
- 相关常量定义在 `src/constants/logger.ts`:
|
|
1202
|
-
- `DEBUG_LOG_PREFIX`:控制台调试输出的日志前缀标识
|
|
1203
|
-
- `DEBUG_TIMESTAMP_FORMAT`:时间戳格式(`HH:mm:ss.SSS`,精简,不含日期)
|
|
1204
|
-
|
|
1205
|
-
**控制台日志格式:**
|
|
1206
|
-
|
|
1207
|
-
```
|
|
1208
|
-
HH:mm:ss.SSS LEVEL 消息内容
|
|
1209
|
-
```
|
|
1210
|
-
|
|
1211
|
-
**日志级别颜色映射:**
|
|
1212
|
-
|
|
1213
|
-
| 级别 | 颜色 |
|
|
1214
|
-
| ------- | ------ |
|
|
1215
|
-
| `error` | 红色 |
|
|
1216
|
-
| `warn` | 黄色 |
|
|
1217
|
-
| `info` | 青色 |
|
|
1218
|
-
| `debug` | 灰色 |
|
|
1219
|
-
|
|
1220
|
-
**使用示例:**
|
|
1221
|
-
|
|
1222
|
-
```bash
|
|
1223
|
-
clawt run -b feature-login --debug
|
|
1224
|
-
clawt validate -b feature-scheme --debug
|
|
1225
|
-
```
|
|
1226
|
-
|
|
1227
|
-
> **注意:** `--debug` 选项不影响文件日志(file transport),文件日志始终按原有策略写入。控制台输出仅在传入 `--debug` 时启用。
|
|
1228
|
-
|
|
1229
|
-
---
|
|
1230
|
-
|
|
1231
|
-
### 5.10 交互式查看和修改全局配置
|
|
1232
|
-
|
|
1233
|
-
**命令:**
|
|
1234
|
-
|
|
1235
|
-
```bash
|
|
1236
|
-
# 交互式修改配置(等同于 config set 无参数)
|
|
1237
|
-
clawt config
|
|
1238
|
-
|
|
1239
|
-
# 修改配置项(无参数进入交互式,有参数直接设置)
|
|
1240
|
-
clawt config set [key] [value]
|
|
1241
|
-
|
|
1242
|
-
# 获取单个配置项的值
|
|
1243
|
-
clawt config get <key>
|
|
1244
|
-
|
|
1245
|
-
# 将配置恢复为默认值
|
|
1246
|
-
clawt config reset
|
|
1247
|
-
```
|
|
1248
|
-
|
|
1249
|
-
#### 交互式修改配置(`config` / `config set`)
|
|
1250
|
-
|
|
1251
|
-
直接执行 `clawt config` 或 `clawt config set`(不带参数)进入交互式配置修改模式。
|
|
1252
|
-
|
|
1253
|
-
**运行流程:**
|
|
1254
|
-
|
|
1255
|
-
1. 读取全局配置文件 `~/.clawt/config.json`
|
|
1256
|
-
2. 列出所有配置项供用户选择(`Enquirer.Select`),每项显示:
|
|
1257
|
-
- 配置项名称
|
|
1258
|
-
- 当前值(布尔值绿色/黄色,字符串青色)
|
|
1259
|
-
- 配置项描述(灰色)
|
|
1260
|
-
- 对象类型配置项(如 `aliases`)标灰不可选,提示用户通过专用命令管理
|
|
1261
|
-
3. 用户选择某个配置项后,根据值类型自动选择提示策略:
|
|
1262
|
-
- **boolean 类型** → `Select`(true / false)
|
|
1263
|
-
- **number 类型** → `Input`(带数字校验)
|
|
1264
|
-
- **string 类型 + 有 `allowedValues`** → `Select`(枚举列表)
|
|
1265
|
-
- **string 类型 + 无 `allowedValues`** → `Input`(自由输入)
|
|
1266
|
-
4. 将修改后的配置持久化到配置文件
|
|
1267
|
-
5. 输出成功提示:`✓ <key> 已设置为 <value>`
|
|
1268
|
-
|
|
1269
|
-
#### 直接设置配置项(`config set <key> <value>`)
|
|
1270
|
-
|
|
1271
|
-
当带参数执行 `clawt config set <key> <value>` 时,直接修改指定配置项。
|
|
1272
|
-
|
|
1273
|
-
**参数:**
|
|
1274
|
-
|
|
1275
|
-
| 参数 | 必填 | 说明 |
|
|
1276
|
-
| ---- | ---- | ---- |
|
|
1277
|
-
| `key` | 否 | 配置项名称(不传则进入交互式模式) |
|
|
1278
|
-
| `value` | 否 | 配置值(传了 `key` 时必填) |
|
|
1279
|
-
|
|
1280
|
-
**运行流程:**
|
|
1281
|
-
|
|
1282
|
-
1. 校验 `key` 是否为有效的配置项名称(基于 `DEFAULT_CONFIG` 的键列表),无效则输出错误及可用配置项列表
|
|
1283
|
-
2. 校验 `value` 是否缺失,缺失则提示用法:`clawt config set <key> <value>`
|
|
1284
|
-
3. 根据目标配置项的类型解析并校验值:
|
|
1285
|
-
- **boolean** → 仅接受 `true` 或 `false`
|
|
1286
|
-
- **number** → `Number()` 解析,`NaN` 报错
|
|
1287
|
-
- **string + 有 `allowedValues`** → 校验值是否在枚举列表中
|
|
1288
|
-
- **string + 无 `allowedValues`** → 无额外校验
|
|
1289
|
-
4. 加载配置、修改目标项、持久化
|
|
1290
|
-
5. 输出成功提示:`✓ <key> 已设置为 <value>`
|
|
1291
|
-
|
|
1292
|
-
#### 获取单个配置项(`config get <key>`)
|
|
1293
|
-
|
|
1294
|
-
**参数:**
|
|
1295
|
-
|
|
1296
|
-
| 参数 | 必填 | 说明 |
|
|
1297
|
-
| ---- | ---- | ---- |
|
|
1298
|
-
| `key` | 是 | 配置项名称 |
|
|
1299
|
-
|
|
1300
|
-
**运行流程:**
|
|
1301
|
-
|
|
1302
|
-
1. 校验 `key` 是否为有效的配置项名称,无效则输出错误及可用配置项列表
|
|
1303
|
-
2. 读取配置文件,获取目标配置项的值
|
|
1304
|
-
3. 输出:`<key> = <value>`
|
|
1305
|
-
|
|
1306
|
-
#### 恢复默认配置(`config reset`)
|
|
1307
|
-
|
|
1308
|
-
**运行流程:**
|
|
1309
|
-
|
|
1310
|
-
1. 如果配置项 `confirmDestructiveOps` 为 `true`,提示确认(显示即将执行的操作和后果:当前配置将被覆盖为默认值),用户取消则退出
|
|
1311
|
-
2. 将默认配置写入 `~/.clawt/config.json`(覆盖现有配置文件)
|
|
1312
|
-
3. 输出成功提示:`✓ 配置已恢复为默认值`
|
|
1313
|
-
|
|
1314
|
-
**实现要点:**
|
|
1315
|
-
|
|
1316
|
-
- 配置项类型定义:`ConfigItemDefinition` 新增可选字段 `allowedValues`(`readonly string[]`),仅对 string 类型有效,用于枚举值校验和交互式 Select 提示
|
|
1317
|
-
- 值解析与提示策略:`src/utils/config-strategy.ts` 中的 `parseConfigValue()`(CLI 字符串解析)和 `promptConfigValue()`(交互式提示),基于类型和 `allowedValues` 自动分发
|
|
1318
|
-
- `saveConfig(config)`:`src/utils/config.ts` 中新增的通用配置写入函数,将完整配置对象持久化到文件
|
|
1319
|
-
- `formatConfigValue(value)`:支持 boolean、string、number、对象类型(如 `aliases`,按键值对逐行展示)的格式化显示
|
|
1320
|
-
|
|
1321
|
-
---
|
|
1322
|
-
|
|
1323
|
-
### 5.11 在已有 Worktree 中恢复会话
|
|
1324
|
-
|
|
1325
|
-
**命令:**
|
|
1326
|
-
|
|
1327
|
-
```bash
|
|
1328
|
-
# 指定分支名(支持模糊匹配)
|
|
1329
|
-
clawt resume -b <branchName>
|
|
1330
|
-
|
|
1331
|
-
# 不指定分支名(列出所有分支供多选)
|
|
1332
|
-
clawt resume
|
|
1333
|
-
```
|
|
1334
|
-
|
|
1335
|
-
**参数:**
|
|
1336
|
-
|
|
1337
|
-
| 参数 | 必填 | 说明 |
|
|
1338
|
-
| ---- | ---- | ----------------------------------------------------- |
|
|
1339
|
-
| `-b` | 否 | 要恢复的分支名(支持模糊匹配,不传则列出所有分支供多选) |
|
|
1340
|
-
|
|
1341
|
-
**使用场景:**
|
|
1342
|
-
|
|
1343
|
-
当用户之前通过 `clawt run` 或 `clawt create` 创建了 worktree 但会话已结束,希望在该 worktree 中重新打开 Claude Code 交互式界面继续工作。支持一次选中多个分支,自动在独立终端 Tab 中批量恢复。
|
|
1344
|
-
|
|
1345
|
-
**运行流程:**
|
|
1346
|
-
|
|
1347
|
-
1. **主 worktree 校验** (2.1)
|
|
1348
|
-
2. **Claude Code CLI 校验**:确认 `claude` CLI 可用
|
|
1349
|
-
3. **解析目标 worktree(多选模式)**:统一使用 `resolveTargetWorktrees`(多选版本)解析目标 worktree,匹配策略如下:
|
|
1350
|
-
- **未传 `-b` 参数**:
|
|
1351
|
-
- 获取当前项目所有 worktree
|
|
1352
|
-
- 无可用 worktree → 报错退出
|
|
1353
|
-
- 仅 1 个 worktree → 直接使用,无需选择
|
|
1354
|
-
- 多个 worktree → 通过交互式多选列表(Enquirer.MultiSelect)让用户选择(空格选择,回车确认),顶部提供「全选」选项
|
|
1355
|
-
- **传了 `-b` 参数**:
|
|
1356
|
-
1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
|
|
1357
|
-
2. **模糊匹配**(子串匹配,大小写不敏感):
|
|
1358
|
-
- 唯一匹配 → 直接使用
|
|
1359
|
-
- 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
|
|
1360
|
-
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
1361
|
-
4. **根据选中数量自动分发**:
|
|
1362
|
-
- **用户未选择任何分支** → 直接退出
|
|
1363
|
-
- **选中 1 个** → 在当前终端恢复(同原有行为),通过 `launchInteractiveClaude()` 启动(使用 `spawnSync` + `inherit stdio`)
|
|
1364
|
-
- **选中多个** → 进入批量恢复流程(见下文)
|
|
1365
|
-
|
|
1366
|
-
**批量恢复流程:**
|
|
1367
|
-
|
|
1368
|
-
1. **计算会话状态**:一次性遍历所有选中的 worktree,通过 `hasClaudeSessionHistory()` 检测是否存在历史会话,构建 sessionMap 避免重复 I/O
|
|
1369
|
-
2. **输出预览**:列出即将恢复的分支及其会话状态("继续上次对话"或"新对话")
|
|
1370
|
-
3. **用户确认**:提示即将在 N 个独立终端 Tab 中恢复会话,等待用户确认
|
|
1371
|
-
4. **逐个在新终端 Tab 中启动**:通过 `launchInteractiveClaudeInNewTerminal()` 构建 shell 命令并通过 AppleScript 在新终端 Tab 中执行
|
|
1372
|
-
5. **输出完成提示**
|
|
1373
|
-
|
|
1374
|
-
**终端 Tab 管理:**
|
|
1375
|
-
|
|
1376
|
-
批量恢复通过 `openCommandInNewTerminalTab()`(`src/utils/terminal.ts`)在新终端 Tab 中启动 Claude Code。终端类型由配置项 `terminalApp` 控制:
|
|
1377
|
-
|
|
1378
|
-
| 配置值 | 行为 |
|
|
1379
|
-
| ---------- | ------------------------------------------------------------ |
|
|
1380
|
-
| `auto` | 自动检测:优先检测 iTerm2 是否已安装(`/Applications/iTerm.app`),已安装则使用 iTerm2,否则降级到 Terminal.app |
|
|
1381
|
-
| `iterm2` | 强制使用 iTerm2 |
|
|
1382
|
-
| `terminal` | 强制使用 Terminal.app |
|
|
1383
|
-
|
|
1384
|
-
**平台限制:** 批量恢复目前仅支持 macOS 平台(通过 AppleScript 打开终端 Tab)。非 macOS 平台会抛出错误。
|
|
1385
|
-
|
|
1386
|
-
**权限要求:** Terminal.app 通过 System Events 模拟键盘操作(`Cmd+T`)新建 Tab,需要在「系统设置 → 隐私与安全性 → 辅助功能」中授权终端应用。iTerm2 使用原生 AppleScript 接口,无需辅助功能权限。
|
|
1387
|
-
|
|
1388
|
-
启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,与 `clawt run` 不传 `--tasks` 时的交互式界面行为一致。
|
|
1389
|
-
|
|
1390
|
-
**会话自动续接:** 启动前会自动检测该 worktree 是否存在 Claude Code 历史会话(通过检查 `~/.claude/projects/<encoded-path>/` 下是否有 `.jsonl` 文件判断),如果存在则自动追加 `--continue` 参数继续上次对话,否则打开新对话。启动信息中会显示当前模式("继续上次对话"或"新对话")。路径编码规则:将绝对路径中所有非字母数字字符替换为 `-`(与 Claude Code 源码的编码逻辑一致)。
|
|
1391
|
-
|
|
1392
|
-
---
|
|
1393
|
-
|
|
1394
|
-
### 5.12 将主分支代码同步到目标 Worktree
|
|
1395
|
-
|
|
1396
|
-
**命令:**
|
|
1397
|
-
|
|
1398
|
-
```bash
|
|
1399
|
-
# 指定分支名(支持模糊匹配)
|
|
1400
|
-
clawt sync -b <branchName>
|
|
1401
|
-
|
|
1402
|
-
# 不指定分支名(列出所有分支供选择)
|
|
1403
|
-
clawt sync
|
|
1404
|
-
```
|
|
1405
|
-
|
|
1406
|
-
**参数:**
|
|
1407
|
-
|
|
1408
|
-
| 参数 | 必填 | 说明 |
|
|
1409
|
-
| ---- | ---- | ------------------------------------------------------------------------ |
|
|
1410
|
-
| `-b` | 否 | 要同步的分支名(支持模糊匹配,不传则列出所有分支供选择) |
|
|
1411
|
-
|
|
1412
|
-
**使用场景:**
|
|
1413
|
-
|
|
1414
|
-
当目标 worktree 的分支与主分支差异过大(例如主分支有了新的提交),导致 `clawt validate` 的 patch apply 失败时,可以通过 `clawt sync` 将主分支最新代码合并到目标 worktree,使其保持与主分支同步。
|
|
1415
|
-
|
|
1416
|
-
**运行流程:**
|
|
1417
|
-
|
|
1418
|
-
1. **主 worktree 校验** (2.1)
|
|
1419
|
-
2. **解析目标 worktree**:根据 `-b` 参数解析目标 worktree,匹配策略如下:
|
|
1420
|
-
- **未传 `-b` 参数**:
|
|
1421
|
-
- 获取当前项目所有 worktree
|
|
1422
|
-
- 无可用 worktree → 报错退出
|
|
1423
|
-
- 仅 1 个 worktree → 直接使用,无需选择
|
|
1424
|
-
- 多个 worktree → 通过交互式列表(Enquirer.Select)让用户选择
|
|
1425
|
-
- **传了 `-b` 参数**:
|
|
1426
|
-
1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
|
|
1427
|
-
2. **模糊匹配**(子串匹配,大小写不敏感):
|
|
1428
|
-
- 唯一匹配 → 直接使用
|
|
1429
|
-
- 多个匹配 → 通过交互式列表让用户从匹配结果中选择
|
|
1430
|
-
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
1431
|
-
3. 调用 `executeSyncForBranch(targetWorktreePath, branch)` 执行核心同步逻辑
|
|
1432
|
-
|
|
1433
|
-
#### `executeSyncForBranch` — sync 核心操作函数
|
|
1434
|
-
|
|
1435
|
-
`executeSyncForBranch(targetWorktreePath: string, branch: string): SyncResult` 是从 `handleSync` 中抽取的核心同步逻辑,不包含 worktree 解析交互,供 validate 等命令复用。
|
|
1436
|
-
|
|
1437
|
-
**接口定义:**
|
|
1438
|
-
|
|
1439
|
-
```typescript
|
|
1440
|
-
/** sync 核心操作的执行结果 */
|
|
1441
|
-
export interface SyncResult {
|
|
1442
|
-
/** 是否同步成功 */
|
|
1443
|
-
success: boolean;
|
|
1444
|
-
/** 是否存在合并冲突 */
|
|
1445
|
-
hasConflict: boolean;
|
|
1446
|
-
}
|
|
1447
|
-
```
|
|
1448
|
-
|
|
1449
|
-
**执行流程:**
|
|
1450
|
-
|
|
1451
|
-
1. **获取主分支名**:通过 `git rev-parse --abbrev-ref HEAD` 获取主 worktree 当前分支名(不硬编码 main/master)
|
|
1452
|
-
2. **自动保存未提交变更**:检查目标 worktree 是否有未提交修改
|
|
1453
|
-
- 有修改 → 自动执行 `git add . && git commit -m "<AUTO_SAVE_COMMIT_MESSAGE>"` 保存变更(commit message 由常量 `AUTO_SAVE_COMMIT_MESSAGE` 定义,值为 `chore: auto-save before sync`,同时用于 merge 命令的 squash 检测)
|
|
1454
|
-
- 无修改 → 跳过
|
|
1455
|
-
3. **在目标 worktree 中合并主分支**:
|
|
1456
|
-
```bash
|
|
1457
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
1458
|
-
git merge <mainBranch>
|
|
1459
|
-
```
|
|
1460
|
-
4. **冲突处理**:
|
|
1461
|
-
- **有冲突** → 输出警告,提示用户进入目标 worktree 手动解决:
|
|
1462
|
-
```
|
|
1463
|
-
合并存在冲突,请进入目标 worktree 手动解决:
|
|
1464
|
-
cd ~/.clawt/worktrees/<project>/<branchName>
|
|
1465
|
-
解决冲突后执行 git add . && git merge --continue
|
|
1466
|
-
clawt validate -b <branch> 验证变更
|
|
1467
|
-
```
|
|
1468
|
-
- 返回 `{ success: false, hasConflict: true }`
|
|
1469
|
-
- **无冲突** → 继续
|
|
1470
|
-
5. **清除 validate 快照**:合并成功后,如果该分支存在 validate 快照(`.tree` 和 `.head` 文件),自动删除(代码基础已变化,旧快照无效)
|
|
1471
|
-
6. **输出成功提示**并返回 `{ success: true, hasConflict: false }`:
|
|
1472
|
-
```
|
|
1473
|
-
✓ 已将 <mainBranch> 的最新代码同步到 <branchName>
|
|
1474
|
-
```
|
|
1475
|
-
|
|
1476
|
-
---
|
|
1477
|
-
|
|
1478
|
-
### 5.13 重置主 Worktree 工作区和暂存区
|
|
1479
|
-
|
|
1480
|
-
**命令:**
|
|
1481
|
-
|
|
1482
|
-
```bash
|
|
1483
|
-
clawt reset
|
|
1484
|
-
```
|
|
1485
|
-
|
|
1486
|
-
**无参数。**
|
|
1487
|
-
|
|
1488
|
-
**使用场景:**
|
|
1489
|
-
|
|
1490
|
-
当用户通过 `clawt validate` 将分支变更迁移到主 worktree 后,希望快速清除工作区和暂存区的所有修改,恢复到干净状态。与 `clawt validate --clean` 的区别在于:`reset` 仅重置工作区和暂存区,**不删除** validate 快照文件,适用于只想清空变更而保留快照以便后续增量 validate 的场景。
|
|
1491
|
-
|
|
1492
|
-
**运行流程:**
|
|
1493
|
-
|
|
1494
|
-
1. **主 worktree 校验** (2.1)
|
|
1495
|
-
2. **检测工作区状态**:通过 `git status --porcelain` 检测主 worktree 是否有未提交的更改
|
|
1496
|
-
- **工作区干净** → 输出提示 `主 worktree 工作区和暂存区已是干净状态,无需重置`,退出
|
|
1497
|
-
- **工作区不干净** → 继续
|
|
1498
|
-
3. **确认破坏性操作**:如果配置项 `confirmDestructiveOps` 为 `true`,提示确认(显示即将执行的危险指令和操作后果),用户取消则退出
|
|
1499
|
-
4. **重置工作区和暂存区**:
|
|
1500
|
-
```bash
|
|
1501
|
-
git reset --hard
|
|
1502
|
-
git clean -f
|
|
328
|
+
✗ 该项目尚未初始化,请先执行 clawt init -b<branchName>设置主工作分支
|
|
1503
329
|
```
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
---
|
|
1510
|
-
|
|
1511
|
-
### 5.14 项目全局状态总览
|
|
1512
|
-
|
|
1513
|
-
**命令:**
|
|
1514
|
-
|
|
1515
|
-
```bash
|
|
1516
|
-
clawt status [--json]
|
|
1517
|
-
```
|
|
1518
|
-
|
|
1519
|
-
**参数:**
|
|
1520
|
-
|
|
1521
|
-
| 参数 | 必填 | 说明 |
|
|
1522
|
-
| -------- | ---- | ---------------------------------------- |
|
|
1523
|
-
| `--json` | 否 | 以 JSON 格式输出完整状态数据 |
|
|
1524
|
-
|
|
1525
|
-
**使用场景:**
|
|
1526
|
-
|
|
1527
|
-
在管理多个 worktree 时,快速了解项目全局状态:主 worktree 当前分支及干净状态、所有 worktree 的变更情况和与主分支的同步状态、validate 快照摘要。
|
|
1528
|
-
|
|
1529
|
-
**运行流程:**
|
|
1530
|
-
|
|
1531
|
-
1. **主 worktree 校验** (2.1)
|
|
1532
|
-
2. **收集主 worktree 状态**:
|
|
1533
|
-
- 获取当前分支名(`getCurrentBranch()`)
|
|
1534
|
-
- 检测工作区是否干净(`isWorkingDirClean()`)
|
|
1535
|
-
- 获取项目名(`getProjectName()`)
|
|
1536
|
-
3. **收集各 worktree 详细状态**:
|
|
1537
|
-
- 获取项目所有 worktree(`getProjectWorktrees()`)
|
|
1538
|
-
- 对每个 worktree 收集以下信息:
|
|
1539
|
-
- **变更状态**(优先级:合并冲突 > 未提交修改 > 已提交 > 无变更)
|
|
1540
|
-
- **行数差异**(新增/删除行数,通过 `getDiffStat()` 获取)
|
|
1541
|
-
- **提交差异**(相对于主分支的领先提交数 `getCommitCountAhead()` 和落后提交数 `getCommitCountBehind()`)
|
|
1542
|
-
- **快照时间**(validate 快照文件的 mtime,通过 `getSnapshotModifiedTime()` 获取,返回 ISO 8601 时间字符串或 null)
|
|
1543
|
-
- **分支创建时间**(通过 `getBranchCreatedAt()` 从 git reflog 获取分支创建时的时间戳)
|
|
1544
|
-
4. **收集 validate 快照摘要**:
|
|
1545
|
-
- 通过 `getProjectSnapshotBranches()` 扫描快照目录下的 `.tree` 文件获取所有存在快照的分支名
|
|
1546
|
-
- 统计快照总数和孤立快照数(对应 worktree 已不存在的快照)
|
|
1547
|
-
5. **输出状态信息**:
|
|
1548
|
-
- 指定 `--json` → 以 JSON 格式输出完整状态数据(`JSON.stringify`)
|
|
1549
|
-
- 未指定 → 以文本格式输出
|
|
1550
|
-
|
|
1551
|
-
**文本输出格式(默认):**
|
|
1552
|
-
|
|
1553
|
-
输出分为三个区块:主 Worktree、Worktree 列表、Validate 快照摘要。每个 worktree 条目每行展示一种信息。
|
|
1554
|
-
|
|
1555
|
-
```
|
|
1556
|
-
════════════════════════════════════════
|
|
1557
|
-
项目状态总览: main-project
|
|
1558
|
-
════════════════════════════════════════
|
|
1559
|
-
|
|
1560
|
-
◆ 主 Worktree
|
|
1561
|
-
分支: main
|
|
1562
|
-
状态: ✓ 干净
|
|
1563
|
-
|
|
1564
|
-
────────────────────────────────────────
|
|
1565
|
-
|
|
1566
|
-
◆ Worktree 列表 (2 个)
|
|
1567
|
-
|
|
1568
|
-
● feature-login [已提交]
|
|
1569
|
-
+120 -30 3 个本地提交 与主分支同步
|
|
1570
|
-
创建于 3 天前
|
|
1571
|
-
上次验证: 2 小时前
|
|
1572
|
-
|
|
1573
|
-
● feature-signup [未提交修改]
|
|
1574
|
-
+45 -10 1 个本地提交 落后主分支 2 个提交
|
|
1575
|
-
创建于 1 天前
|
|
1576
|
-
✗ 未验证
|
|
1577
|
-
|
|
1578
|
-
────────────────────────────────────────
|
|
1579
|
-
|
|
1580
|
-
◆ Validate 快照 (3 个)
|
|
1581
|
-
其中 1 个快照对应的 worktree 已不存在
|
|
1582
|
-
|
|
1583
|
-
════════════════════════════════════════
|
|
1584
|
-
```
|
|
1585
|
-
|
|
1586
|
-
**变更状态标签:**
|
|
1587
|
-
|
|
1588
|
-
| 状态 | 标签 | 颜色 | 说明 |
|
|
1589
|
-
| ----------- | -------------- | ------ | ----------------------------- |
|
|
1590
|
-
| `committed` | 已提交 | 绿色 | 有已提交内容,工作区干净 |
|
|
1591
|
-
| `uncommitted` | 未提交修改 | 黄色 | 有未提交的修改 |
|
|
1592
|
-
| `conflict` | 合并冲突 | 红色 | 存在合并冲突 |
|
|
1593
|
-
| `clean` | 无变更 | 灰色 | 工作区干净且无本地提交 |
|
|
1594
|
-
|
|
1595
|
-
**差异统计行展示规则:**
|
|
1596
|
-
|
|
1597
|
-
- 行数变更(`+N -N`)仅在有变更时展示
|
|
1598
|
-
- 本地提交数(`N 个本地提交`)仅在有提交时展示
|
|
1599
|
-
- 与主分支同步状态始终展示(落后时显示黄色,同步时显示绿色)
|
|
1600
|
-
|
|
1601
|
-
**分支创建时间行:**
|
|
1602
|
-
|
|
1603
|
-
- 通过 `getBranchCreatedAt()` 从 git reflog 获取分支创建时间,以 `formatRelativeTime()` 格式化为中文相对时间(如"3 天前"、"2 小时前"、"刚刚")
|
|
1604
|
-
- 展示为灰色文本 `创建于 X前`,无法获取时不展示
|
|
1605
|
-
|
|
1606
|
-
**验证状态行:**
|
|
1607
|
-
|
|
1608
|
-
- 有快照时:显示绿色 `上次验证: X前`(通过 `getSnapshotModifiedTime()` 获取快照文件 mtime,再用 `formatRelativeTime()` 格式化)
|
|
1609
|
-
- 无快照时:显示红色 `✗ 未验证` 警示
|
|
1610
|
-
|
|
1611
|
-
**快照区块:**
|
|
1612
|
-
|
|
1613
|
-
- 标题显示快照总数
|
|
1614
|
-
- 如果存在孤立快照(对应 worktree 已不存在),显示黄色警告 `其中 N 个快照对应的 worktree 已不存在`
|
|
1615
|
-
- 无孤立快照时不显示额外信息
|
|
1616
|
-
|
|
1617
|
-
**JSON 输出格式(`--json`):**
|
|
1618
|
-
|
|
1619
|
-
```json
|
|
1620
|
-
{
|
|
1621
|
-
"main": {
|
|
1622
|
-
"branch": "main",
|
|
1623
|
-
"isClean": true,
|
|
1624
|
-
"projectName": "main-project"
|
|
1625
|
-
},
|
|
1626
|
-
"worktrees": [
|
|
1627
|
-
{
|
|
1628
|
-
"path": "~/.clawt/worktrees/main-project/feature-login",
|
|
1629
|
-
"branch": "feature-login",
|
|
1630
|
-
"changeStatus": "committed",
|
|
1631
|
-
"commitsAhead": 3,
|
|
1632
|
-
"commitsBehind": 0,
|
|
1633
|
-
"snapshotTime": "2025-02-06T12:30:00.000Z",
|
|
1634
|
-
"insertions": 120,
|
|
1635
|
-
"deletions": 30,
|
|
1636
|
-
"createdAt": "2025-02-03T10:00:00.000Z"
|
|
1637
|
-
}
|
|
1638
|
-
],
|
|
1639
|
-
"snapshots": {
|
|
1640
|
-
"total": 3,
|
|
1641
|
-
"orphaned": 1
|
|
1642
|
-
},
|
|
1643
|
-
"totalWorktrees": 1
|
|
1644
|
-
}
|
|
1645
|
-
```
|
|
1646
|
-
|
|
1647
|
-
**实现要点:**
|
|
1648
|
-
|
|
1649
|
-
- 类型定义在 `src/types/status.ts`:`WorktreeDetailedStatus`(`hasSnapshot` 已改为 `snapshotTime: string | null`,新增 `createdAt: string | null`)、`MainWorktreeStatus`、`SnapshotInfo`、`SnapshotSummary`(新增,包含 `total` 和 `orphaned`)、`StatusResult`(`snapshots` 已从 `SnapshotInfo[]` 改为 `SnapshotSummary`)
|
|
1650
|
-
- 消息常量在 `MESSAGES.STATUS_*` 系列,新增:
|
|
1651
|
-
- `STATUS_LAST_VALIDATED`:上次验证时间标签(如 `上次验证: 2 小时前`)
|
|
1652
|
-
- `STATUS_NOT_VALIDATED`:未验证红色警示文本(`✗ 未验证`)
|
|
1653
|
-
- `STATUS_CREATED_AT`:分支创建时间标签(如 `创建于 3 天前`)
|
|
1654
|
-
- `STATUS_SNAPSHOT_ORPHANED`:改为接受数量参数的函数(如 `其中 1 个快照对应的 worktree 已不存在`)
|
|
1655
|
-
- `getBranchCreatedAt()` 是新增的工具函数(在 `src/utils/git.ts`),通过 `git reflog show <branch> --format=%cI` 获取 reflog 最后一条记录的时间戳(即分支创建时间),返回 ISO 8601 格式字符串或 null
|
|
1656
|
-
- `getSnapshotModifiedTime()` 是新增的工具函数(在 `src/utils/validate-snapshot.ts`),通过 `fs.statSync` 获取快照文件的修改时间(mtime),返回 ISO 8601 格式字符串或 null
|
|
1657
|
-
- `formatRelativeTime()` 是新增的格式化函数(在 `src/utils/formatter.ts`),将 ISO 8601 日期字符串转换为中文相对时间描述(如"3 天前"、"2 小时前"、"刚刚"),无效日期时返回 null
|
|
1658
|
-
- `getCommitCountBehind()` 是新增的工具函数(在 `src/utils/git.ts`),通过 `git rev-list --count <branch>..HEAD` 计算落后提交数
|
|
1659
|
-
- `getProjectSnapshotBranches()` 是新增的工具函数(在 `src/utils/validate-snapshot.ts`),通过扫描快照目录下的 `.tree` 文件提取分支名列表
|
|
1660
|
-
- `formatDiskSize()` 是新增的格式化函数(在 `src/utils/formatter.ts`),将字节数格式化为带单位的磁盘大小字符串(如 `"1.5 GB"`、`"256.0 MB"`、`"10.2 KB"`、`"512 B"`)
|
|
1661
|
-
- `formatLocalISOString()` 是新增的格式化函数(在 `src/utils/formatter.ts`),将 Date 对象格式化为本机时区的 ISO 8601 字符串(输出格式: `YYYY-MM-DDTHH:mm:ss.sss+HH:MM`),替代 `Date.toISOString()` 的 UTC 时区输出
|
|
1662
|
-
- `calculateDirSize()` 是新增的文件系统工具函数(在 `src/utils/fs.ts`),递归计算目录占用的磁盘大小(字节),遇到无法访问的文件或目录时静默跳过
|
|
1663
|
-
|
|
1664
|
-
---
|
|
1665
|
-
|
|
1666
|
-
### 5.15 命令别名管理
|
|
1667
|
-
|
|
1668
|
-
**命令:**
|
|
1669
|
-
|
|
1670
|
-
```bash
|
|
1671
|
-
# 列出所有命令别名
|
|
1672
|
-
clawt alias
|
|
1673
|
-
clawt alias list
|
|
1674
|
-
|
|
1675
|
-
# 设置命令别名
|
|
1676
|
-
clawt alias set <alias> <command>
|
|
1677
|
-
|
|
1678
|
-
# 移除命令别名
|
|
1679
|
-
clawt alias remove <alias>
|
|
1680
|
-
```
|
|
1681
|
-
|
|
1682
|
-
**子命令:**
|
|
1683
|
-
|
|
1684
|
-
| 子命令 | 说明 |
|
|
1685
|
-
| ------ | ---- |
|
|
1686
|
-
| `clawt alias` / `clawt alias list` | 列出所有已配置的命令别名 |
|
|
1687
|
-
| `clawt alias set <alias> <command>` | 设置命令别名,将 `<alias>` 映射到 `<command>` |
|
|
1688
|
-
| `clawt alias remove <alias>` | 移除指定的命令别名 |
|
|
1689
|
-
|
|
1690
|
-
**参数:**
|
|
1691
|
-
|
|
1692
|
-
| 参数 | 必填 | 说明 |
|
|
1693
|
-
| ---- | ---- | ---- |
|
|
1694
|
-
| `<alias>` | 是(set / remove) | 别名名称 |
|
|
1695
|
-
| `<command>` | 是(set) | 目标内置命令名 |
|
|
1696
|
-
|
|
1697
|
-
**约束规则:**
|
|
1698
|
-
|
|
1699
|
-
1. **别名不能覆盖内置命令名**:别名不能与已注册的内置命令同名(`list`、`create`、`remove`、`run`、`resume`、`validate`、`merge`、`config`、`sync`、`reset`、`status`、`alias`)。如果用户尝试设置与内置命令同名的别名,报错退出
|
|
1700
|
-
2. **目标必须是内置命令**:别名的目标(`<command>`)必须是已注册的内置命令名。如果指定了不存在的目标命令,报错退出
|
|
1701
|
-
3. **参数透传**:通过别名调用时,所有选项和参数会完全透传给目标命令,行为与直接调用目标命令完全一致
|
|
1702
|
-
|
|
1703
|
-
**持久化:**
|
|
1704
|
-
|
|
1705
|
-
别名配置存储在 `~/.clawt/config.json` 的 `aliases` 字段中(类型 `Record<string, string>`,默认 `{}`)。
|
|
1706
|
-
|
|
1707
|
-
**运行流程:**
|
|
1708
|
-
|
|
1709
|
-
#### `alias list`(默认)
|
|
1710
|
-
|
|
1711
|
-
1. 读取配置文件中的 `aliases` 字段
|
|
1712
|
-
2. 如果没有配置任何别名,输出提示 `当前没有配置任何命令别名`
|
|
1713
|
-
3. 如果有别名,逐行输出所有别名映射
|
|
1714
|
-
|
|
1715
|
-
**输出格式:**
|
|
1716
|
-
|
|
1717
|
-
```
|
|
1718
|
-
命令别名列表:
|
|
1719
|
-
|
|
1720
|
-
l → list
|
|
1721
|
-
r → run
|
|
1722
|
-
v → validate
|
|
1723
|
-
```
|
|
1724
|
-
|
|
1725
|
-
#### `alias set <alias> <command>`
|
|
1726
|
-
|
|
1727
|
-
1. **校验别名不与内置命令冲突**:检查 `<alias>` 是否为内置命令名,是则报错退出
|
|
1728
|
-
2. **校验目标命令存在**:检查 `<command>` 是否为已注册的内置命令名,不是则报错退出
|
|
1729
|
-
3. 将别名写入配置文件的 `aliases` 字段(如果别名已存在,覆盖旧值)
|
|
1730
|
-
4. 输出成功提示
|
|
1731
|
-
|
|
1732
|
-
**输出格式:**
|
|
1733
|
-
|
|
1734
|
-
```
|
|
1735
|
-
✓ 已设置别名: l → list
|
|
1736
|
-
```
|
|
1737
|
-
|
|
1738
|
-
#### `alias remove <alias>`
|
|
1739
|
-
|
|
1740
|
-
1. 读取配置文件中的 `aliases` 字段
|
|
1741
|
-
2. 检查指定的别名是否存在,不存在则报错退出
|
|
1742
|
-
3. 从 `aliases` 中删除该别名并写入配置文件
|
|
1743
|
-
4. 输出成功提示
|
|
1744
|
-
|
|
1745
|
-
**输出格式:**
|
|
1746
|
-
|
|
1747
|
-
```
|
|
1748
|
-
✓ 已移除别名: l
|
|
1749
|
-
```
|
|
1750
|
-
|
|
1751
|
-
**别名使用示例:**
|
|
1752
|
-
|
|
1753
|
-
```bash
|
|
1754
|
-
# 设置别名
|
|
1755
|
-
clawt alias set l list
|
|
1756
|
-
clawt alias set r run
|
|
1757
|
-
clawt alias set v validate
|
|
1758
|
-
|
|
1759
|
-
# 使用别名(等同于对应的完整命令)
|
|
1760
|
-
clawt l # 等同于 clawt list
|
|
1761
|
-
clawt r task.md # 等同于 clawt run task.md
|
|
1762
|
-
|
|
1763
|
-
# 查看所有别名
|
|
1764
|
-
clawt alias list
|
|
1765
|
-
|
|
1766
|
-
# 移除别名
|
|
1767
|
-
clawt alias remove l
|
|
1768
|
-
```
|
|
1769
|
-
|
|
1770
|
-
---
|
|
1771
|
-
|
|
1772
|
-
### 5.16 `clawt completion` 命令
|
|
1773
|
-
|
|
1774
|
-
为终端环境(bash/zsh)生成并安装 `clawt` 的命令、选项及参数的自动补全脚本。
|
|
1775
|
-
|
|
1776
|
-
#### 语法
|
|
1777
|
-
```bash
|
|
1778
|
-
clawt completion bash
|
|
1779
|
-
clawt completion zsh
|
|
1780
|
-
clawt completion install
|
|
1781
|
-
```
|
|
1782
|
-
|
|
1783
|
-
#### 子命令说明
|
|
1784
|
-
|
|
1785
|
-
| 子命令 | 说明 |
|
|
1786
|
-
| --------- | ----------------------------------------------------------------------------------- |
|
|
1787
|
-
| `bash` | 输出适用于 bash 的补全脚本(用户可重定向到 `~/.bashrc`) |
|
|
1788
|
-
| `zsh` | 输出适用于 zsh 的补全脚本(用户可重定向到 `~/.zshrc`) |
|
|
1789
|
-
| `install` | 自动检测当前 shell 类型,将补全脚本追加到对应的配置文件中 |
|
|
1790
|
-
|
|
1791
|
-
#### `install` 子命令流程
|
|
1792
|
-
|
|
1793
|
-
1. 通过 `process.env.SHELL` 检测当前 shell 类型
|
|
1794
|
-
2. 根据 shell 类型确定目标配置文件:
|
|
1795
|
-
- zsh → `~/.zshrc`(追加 `source <(clawt completion zsh)`)
|
|
1796
|
-
- bash → `~/.bashrc`(追加 `eval "$(clawt completion bash)"`)
|
|
1797
|
-
3. 检查目标文件中是否已包含 `clawt completion`,已存在则跳过并提示
|
|
1798
|
-
4. 追加成功后提示用户重启终端或 source 配置文件
|
|
1799
|
-
5. 未知 shell 类型时输出警告,提示手动配置
|
|
1800
|
-
|
|
1801
|
-
#### 动态补全特性
|
|
1802
|
-
|
|
1803
|
-
补全脚本通过内部子命令 `_complete` 实现动态补全,不对外公开。补全引擎基于 Commander.js 的命令树结构遍历,支持以下场景:
|
|
1804
|
-
|
|
1805
|
-
| 场景 | 补全行为 |
|
|
1806
|
-
| ---------------------------- | ---------------------------------------------------------- |
|
|
1807
|
-
| `-b` / `--branch` 参数之后 | 动态列出当前项目所有 worktree 分支名(通过 `getProjectWorktrees`) |
|
|
1808
|
-
| `-f` / `--file` 参数之后 | 动态列出匹配的文件和子目录(不限制文件类型,支持子目录递归浏览) |
|
|
1809
|
-
| `config set` / `config get` 之后 | 动态列出所有配置项键名(从 `CONFIG_DEFINITIONS` 获取) |
|
|
1810
|
-
| 输入以 `-` 开头 | 列出当前命令层级的可用选项(short/long) |
|
|
1811
|
-
| 其他情况 | 列出当前命令层级的可用子命令及别名 |
|
|
1812
|
-
|
|
1813
|
-
**文件路径补全细节:**
|
|
1814
|
-
- 支持子目录递归浏览(如 `tasks/` 后继续 Tab 可深入子目录)
|
|
1815
|
-
- 目录候选项以 `/` 结尾,补全时不自动追加空格
|
|
1816
|
-
- 不限制文件类型,列出所有非隐藏文件
|
|
1817
|
-
- 跳过隐藏文件和目录(以 `.` 开头)
|
|
1818
|
-
|
|
1819
|
-
#### 实现说明
|
|
1820
|
-
|
|
1821
|
-
- 补全命令注册函数:`registerCompletionCommand()`(在 `src/commands/completion.ts`)
|
|
1822
|
-
- 消息常量:`COMPLETION_MESSAGES`(在 `src/constants/messages/completion.ts`)
|
|
1823
|
-
- 核心函数:`generateCompletions()` 解析当前输入上下文并输出候选项,`completeFilePath()` 处理文件路径补全
|
|
1824
|
-
- shell 脚本生成:`getBashScript()`、`getZshScript()` 分别生成对应 shell 的补全脚本
|
|
1825
|
-
|
|
1826
|
-
---
|
|
1827
|
-
|
|
1828
|
-
### 5.17 自动更新检查
|
|
1829
|
-
|
|
1830
|
-
CLI 在每次命令执行完毕后,根据配置项 `autoUpdate` 决定是否检查 npm registry 上的最新版本。当发现新版本时,以带边框的提示框在终端输出版本更新信息和升级命令。
|
|
1831
|
-
|
|
1832
|
-
#### 触发条件
|
|
1833
|
-
|
|
1834
|
-
- 配置项 `autoUpdate` 为 `true`(默认启用)
|
|
1835
|
-
- 命令正常执行完毕后触发(在 `program.parseAsync()` 之后)
|
|
1836
|
-
|
|
1837
|
-
#### 检查流程
|
|
1838
|
-
|
|
1839
|
-
1. 读取缓存文件 `~/.clawt/update-check.json`
|
|
1840
|
-
2. 判断缓存是否有效:
|
|
1841
|
-
- 缓存不存在或解析失败 → 视为过期
|
|
1842
|
-
- 缓存中的 `currentVersion` 与本地版本不一致 → 视为过期
|
|
1843
|
-
- 距离上次检查超过 24 小时 → 视为过期
|
|
1844
|
-
3. **缓存有效**:直接使用缓存中的 `latestVersion` 与本地版本比较,有新版本则打印提示
|
|
1845
|
-
4. **缓存过期**:向 npm registry 发起 HTTPS 请求获取最新版本号(5 秒超时),更新缓存文件后判断并打印提示
|
|
1846
|
-
|
|
1847
|
-
#### 缓存文件
|
|
1848
|
-
|
|
1849
|
-
**路径:** `~/.clawt/update-check.json`
|
|
1850
|
-
|
|
1851
|
-
**结构:**
|
|
1852
|
-
|
|
1853
|
-
```json
|
|
1854
|
-
{
|
|
1855
|
-
"lastCheck": 1709000000000,
|
|
1856
|
-
"latestVersion": "2.18.0",
|
|
1857
|
-
"currentVersion": "2.17.1"
|
|
1858
|
-
}
|
|
1859
|
-
```
|
|
1860
|
-
|
|
1861
|
-
| 字段 | 类型 | 说明 |
|
|
1862
|
-
| ---- | ---- | ---- |
|
|
1863
|
-
| `lastCheck` | `number` | 上次检查时间戳(毫秒) |
|
|
1864
|
-
| `latestVersion` | `string` | 从 registry 获取的最新版本号 |
|
|
1865
|
-
| `currentVersion` | `string` | 检查时的本地版本号 |
|
|
1866
|
-
|
|
1867
|
-
#### 版本比较
|
|
1868
|
-
|
|
1869
|
-
使用简易 semver 比较(不引入额外依赖),逐级比较 `major.minor.patch`:
|
|
1870
|
-
|
|
1871
|
-
- `latest > current` → 提示更新
|
|
1872
|
-
- `latest <= current` → 不提示
|
|
1873
|
-
|
|
1874
|
-
#### 包管理器检测
|
|
1875
|
-
|
|
1876
|
-
更新提示中会显示与用户安装方式匹配的升级命令。检测逻辑依次尝试:
|
|
1877
|
-
|
|
1878
|
-
1. `pnpm list -g --depth=0 clawt` → 匹配则提示 `pnpm add -g clawt`
|
|
1879
|
-
2. `yarn global list --depth=0` → 输出含 `clawt` 则提示 `yarn global add clawt`
|
|
1880
|
-
3. 以上均未匹配 → 默认提示 `npm i -g clawt`
|
|
1881
|
-
|
|
1882
|
-
#### 提示框格式
|
|
1883
|
-
|
|
1884
|
-
当检测到新版本时,输出带 Unicode 圆角边框的居中提示框:
|
|
1885
|
-
|
|
1886
|
-
```
|
|
1887
|
-
╭──────────────────────────────────────────────╮
|
|
1888
|
-
│ │
|
|
1889
|
-
│ clawt 有新版本可用: 2.17.1 → 2.18.0 │
|
|
1890
|
-
│ 执行 npm i -g clawt 进行更新 │
|
|
1891
|
-
│ │
|
|
1892
|
-
╰──────────────────────────────────────────────╯
|
|
1893
|
-
```
|
|
1894
|
-
|
|
1895
|
-
版本号和命令使用 chalk 着色:当前版本红色、最新版本绿色、更新命令青色。
|
|
1896
|
-
|
|
1897
|
-
#### 容错设计
|
|
1898
|
-
|
|
1899
|
-
所有异常静默处理,不影响 CLI 正常功能:
|
|
1900
|
-
|
|
1901
|
-
- 网络请求失败或超时(5 秒) → 静默忽略
|
|
1902
|
-
- registry 返回无效 JSON 或缺少 `version` 字段 → 静默忽略
|
|
1903
|
-
- 缓存文件读写失败 → 静默忽略
|
|
1904
|
-
- `checkForUpdates()` 入口函数的最外层 `try/catch` 确保任何未预期异常都不会中断 CLI
|
|
1905
|
-
|
|
1906
|
-
#### 常量定义
|
|
1907
|
-
|
|
1908
|
-
| 常量 | 值 | 位置 |
|
|
1909
|
-
| ---- | -- | ---- |
|
|
1910
|
-
| `UPDATE_CHECK_INTERVAL_MS` | `86400000`(24 小时) | `src/constants/update.ts` |
|
|
1911
|
-
| `NPM_REGISTRY_URL` | `https://registry.npmjs.org/clawt/latest` | `src/constants/update.ts` |
|
|
1912
|
-
| `NPM_REGISTRY_TIMEOUT_MS` | `5000` | `src/constants/update.ts` |
|
|
1913
|
-
| `PACKAGE_NAME` | `clawt` | `src/constants/update.ts` |
|
|
1914
|
-
| `UPDATE_CHECK_PATH` | `~/.clawt/update-check.json` | `src/constants/paths.ts` |
|
|
1915
|
-
|
|
1916
|
-
#### 实现说明
|
|
1917
|
-
|
|
1918
|
-
- 入口函数:`checkForUpdates()`(在 `src/utils/update-checker.ts`)
|
|
1919
|
-
- 消息常量:`UPDATE_MESSAGES`、`UPDATE_COMMANDS`(在 `src/constants/messages/update.ts`)
|
|
1920
|
-
- 入口调用点:`src/index.ts` 的 `main()` 异步函数中,`program.parseAsync()` 之后根据 `config.autoUpdate` 条件调用
|
|
1921
|
-
|
|
1922
|
-
---
|
|
1923
|
-
|
|
1924
|
-
### 5.18 跨项目 Worktree 概览
|
|
1925
|
-
|
|
1926
|
-
**命令:**
|
|
1927
|
-
|
|
1928
|
-
```bash
|
|
1929
|
-
clawt projects [name] [--json]
|
|
1930
|
-
```
|
|
1931
|
-
|
|
1932
|
-
**参数:**
|
|
1933
|
-
|
|
1934
|
-
| 参数 | 必填 | 说明 |
|
|
1935
|
-
| -------- | ---- | ---------------------------------------------- |
|
|
1936
|
-
| `[name]` | 否 | 指定项目名,查看该项目的 worktree 详情 |
|
|
1937
|
-
| `--json` | 否 | 以 JSON 格式输出完整数据 |
|
|
1938
|
-
|
|
1939
|
-
**使用场景:**
|
|
1940
|
-
|
|
1941
|
-
当使用 clawt 管理多个不同项目时,快速了解所有项目的 worktree 数量、磁盘占用和最近活跃时间。也可以指定项目名查看该项目下每个 worktree 的分支、路径、最后修改时间和磁盘占用。
|
|
1942
|
-
|
|
1943
|
-
**注意:** `projects` 命令不需要在主 worktree 中执行(与其他命令不同),它直接扫描 `~/.clawt/worktrees/` 目录。
|
|
1944
|
-
|
|
1945
|
-
**运行流程:**
|
|
1946
|
-
|
|
1947
|
-
#### 无参数模式(项目概览)
|
|
1948
|
-
|
|
1949
|
-
1. 扫描 `~/.clawt/worktrees/` 目录,列出所有项目子目录
|
|
1950
|
-
2. 对每个项目收集以下信息:
|
|
1951
|
-
- **项目名**(目录名即项目名)
|
|
1952
|
-
- **worktree 数量**(项目目录下的子目录数)
|
|
1953
|
-
- **最近活跃时间**(取项目目录自身和所有 worktree 目录 mtime 的最大值,通过 `formatLocalISOString()` 格式化为本机时区的 ISO 8601 字符串)
|
|
1954
|
-
- **磁盘占用**(通过 `calculateDirSize()` 递归计算整个项目目录的总大小)
|
|
1955
|
-
3. 按最近活跃时间降序排序
|
|
1956
|
-
4. 输出概览信息(文本或 JSON)
|
|
1957
|
-
|
|
1958
|
-
#### 指定项目模式(worktree 详情)
|
|
1959
|
-
|
|
1960
|
-
1. 检查 `~/.clawt/worktrees/<name>/` 是否存在,不存在则报错退出
|
|
1961
|
-
2. 扫描项目目录,对每个 worktree 子目录收集:
|
|
1962
|
-
- **分支名**(目录名即分支名)
|
|
1963
|
-
- **worktree 路径**
|
|
1964
|
-
- **最后修改时间**(目录 mtime,通过 `formatLocalISOString()` 格式化)
|
|
1965
|
-
- **磁盘占用**(通过 `calculateDirSize()` 递归计算)
|
|
1966
|
-
3. 按最后修改时间降序排序
|
|
1967
|
-
4. 输出详情信息(文本或 JSON)
|
|
1968
|
-
|
|
1969
|
-
**文本输出格式(概览模式):**
|
|
1970
|
-
|
|
1971
|
-
```
|
|
1972
|
-
════════════════════════════════════════
|
|
1973
|
-
项目概览
|
|
1974
|
-
════════════════════════════════════════
|
|
1975
|
-
|
|
1976
|
-
● my-project
|
|
1977
|
-
3 个 worktree 最近活跃: 2 小时前 磁盘占用: 1.5 GB
|
|
1978
|
-
|
|
1979
|
-
● another-project
|
|
1980
|
-
1 个 worktree 最近活跃: 3 天前 磁盘占用: 256.0 MB
|
|
1981
|
-
|
|
1982
|
-
────────────────────────────────────────
|
|
1983
|
-
|
|
1984
|
-
共 2 个项目 总占用: 1.8 GB
|
|
1985
|
-
|
|
1986
|
-
════════════════════════════════════════
|
|
1987
|
-
```
|
|
1988
|
-
|
|
1989
|
-
**文本输出格式(详情模式):**
|
|
1990
|
-
|
|
1991
|
-
```
|
|
1992
|
-
════════════════════════════════════════
|
|
1993
|
-
项目详情: my-project
|
|
1994
|
-
════════════════════════════════════════
|
|
1995
|
-
|
|
1996
|
-
◆ 路径: ~/.clawt/worktrees/my-project
|
|
1997
|
-
总占用: 1.5 GB
|
|
1998
|
-
|
|
1999
|
-
────────────────────────────────────────
|
|
2000
|
-
|
|
2001
|
-
● feature-login
|
|
2002
|
-
~/.clawt/worktrees/my-project/feature-login
|
|
2003
|
-
最后修改: 2 小时前 磁盘占用: 800.0 MB
|
|
2004
|
-
|
|
2005
|
-
● feature-signup
|
|
2006
|
-
~/.clawt/worktrees/my-project/feature-signup
|
|
2007
|
-
最后修改: 1 天前 磁盘占用: 700.0 MB
|
|
2008
|
-
|
|
2009
|
-
════════════════════════════════════════
|
|
2010
|
-
```
|
|
2011
|
-
|
|
2012
|
-
**JSON 输出格式(概览模式,`--json`):**
|
|
2013
|
-
|
|
2014
|
-
```json
|
|
2015
|
-
{
|
|
2016
|
-
"projects": [
|
|
2017
|
-
{
|
|
2018
|
-
"name": "my-project",
|
|
2019
|
-
"worktreeCount": 3,
|
|
2020
|
-
"lastActiveTime": "2025-06-15T18:30:00.000+08:00",
|
|
2021
|
-
"diskUsage": 1610612736
|
|
2022
|
-
}
|
|
2023
|
-
],
|
|
2024
|
-
"totalProjects": 1,
|
|
2025
|
-
"totalDiskUsage": 1610612736
|
|
2026
|
-
}
|
|
2027
|
-
```
|
|
2028
|
-
|
|
2029
|
-
**JSON 输出格式(详情模式,`--json`):**
|
|
2030
|
-
|
|
2031
|
-
```json
|
|
2032
|
-
{
|
|
2033
|
-
"name": "my-project",
|
|
2034
|
-
"projectDir": "~/.clawt/worktrees/my-project",
|
|
2035
|
-
"worktrees": [
|
|
2036
|
-
{
|
|
2037
|
-
"branch": "feature-login",
|
|
2038
|
-
"path": "~/.clawt/worktrees/my-project/feature-login",
|
|
2039
|
-
"lastModifiedTime": "2025-06-15T18:30:00.000+08:00",
|
|
2040
|
-
"diskUsage": 838860800
|
|
2041
|
-
}
|
|
2042
|
-
],
|
|
2043
|
-
"totalDiskUsage": 838860800
|
|
2044
|
-
}
|
|
2045
|
-
```
|
|
2046
|
-
|
|
2047
|
-
**实现要点:**
|
|
2048
|
-
|
|
2049
|
-
- 命令注册函数:`registerProjectsCommand()`(在 `src/commands/projects.ts`)
|
|
2050
|
-
- 类型定义在 `src/types/project.ts`:`ProjectOverview`、`ProjectWorktreeDetail`、`ProjectDetailResult`、`ProjectsOverviewResult`
|
|
2051
|
-
- 命令选项类型:`ProjectsOptions`(在 `src/types/command.ts`)
|
|
2052
|
-
- 消息常量在 `PROJECTS_MESSAGES`(在 `src/constants/messages/projects.ts`)
|
|
2053
|
-
- 时间格式化使用 `formatLocalISOString()`(在 `src/utils/formatter.ts`),输出本机时区的 ISO 8601 字符串(替代 `Date.toISOString()` 的 UTC 输出)
|
|
2054
|
-
- 磁盘大小展示使用 `formatDiskSize()`(在 `src/utils/formatter.ts`),将字节数格式化为带单位的可读字符串
|
|
2055
|
-
- 目录大小计算使用 `calculateDirSize()`(在 `src/utils/fs.ts`),递归遍历目录计算总字节数
|
|
2056
|
-
- 时间的相对展示使用 `formatRelativeTime()`(在 `src/utils/formatter.ts`),将 ISO 8601 日期转换为中文相对时间(如"2 小时前")
|
|
330
|
+
其他命令(list、resume、config、status、alias、projects、completion)不受影响,无需添加该校验。
|
|
331
|
+
> **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、validate、sync、remove、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。仅 reset 命令因不调用 `ensureOnMainWorkBranch`,需要自行调用 `requireProjectConfig()`。
|
|
332
|
+
3. **主分支名统一从项目级配置获取**:所有需要获取主分支名的场景(sync 中合并主分支、merge 中计算 merge-base、切回主分支等),统一使用项目级配置中的 `clawtMainWorkBranch`,不再通过 `getCurrentBranch(mainWorktreePath)` 动态获取。因为在新架构下,主 worktree 可能处于验证分支上,`getCurrentBranch` 会返回验证分支名而非真正的主工作分支名。
|
|
333
|
+
4. **测试文件全量更新**:本次重构涉及的所有命令(init、create、run、validate、sync、remove、merge、reset),其对应的测试文件必须同步更新,确保覆盖新增的验证分支逻辑、项目级配置逻辑和变更后的流程。
|
|
2057
334
|
|
|
2058
335
|
---
|
|
2059
336
|
|
|
2060
|
-
##
|
|
337
|
+
## 7. 错误处理规范
|
|
2061
338
|
|
|
2062
|
-
###
|
|
339
|
+
### 7.1 通用错误处理
|
|
2063
340
|
|
|
2064
341
|
| 错误场景 | 处理方式 |
|
|
2065
342
|
| --------------------------------- | ---------------------------------------------------------- |
|
|
@@ -2071,7 +348,7 @@ clawt projects [name] [--json]
|
|
|
2071
348
|
| Git 命令执行失败 | 捕获 stderr,记录日志,输出错误提示,退出 (exit code 1) |
|
|
2072
349
|
| 目标 worktree 不存在 | 输出错误提示(列出可用 worktree),退出 (exit code 1) |
|
|
2073
350
|
|
|
2074
|
-
###
|
|
351
|
+
### 7.2 退出码
|
|
2075
352
|
|
|
2076
353
|
| 退出码 | 说明 |
|
|
2077
354
|
| ------ | -------------- |
|
|
@@ -2081,21 +358,21 @@ clawt projects [name] [--json]
|
|
|
2081
358
|
|
|
2082
359
|
---
|
|
2083
360
|
|
|
2084
|
-
##
|
|
361
|
+
## 8. 非功能性需求
|
|
2085
362
|
|
|
2086
|
-
###
|
|
363
|
+
### 8.1 性能
|
|
2087
364
|
|
|
2088
365
|
- Worktree 创建为串行执行(Git worktree 不支持并行写入)
|
|
2089
366
|
- Claude Code 任务为并行执行(各自独立进程)
|
|
2090
367
|
- 任务完成检测:监听子进程 `close` 事件,事件驱动
|
|
2091
368
|
|
|
2092
|
-
###
|
|
369
|
+
### 8.2 兼容性
|
|
2093
370
|
|
|
2094
371
|
- 支持 macOS 和 Linux
|
|
2095
372
|
- Node.js >= 18
|
|
2096
373
|
- Git >= 2.15(worktree 功能稳定版本)
|
|
2097
374
|
|
|
2098
|
-
###
|
|
375
|
+
### 8.3 测试
|
|
2099
376
|
|
|
2100
377
|
- 测试框架:Vitest,配置文件为 `vitest.config.ts`
|
|
2101
378
|
- 覆盖率工具:@vitest/coverage-v8,覆盖率报告格式为 text、lcov、html
|
|
@@ -2115,7 +392,7 @@ clawt projects [name] [--json]
|
|
|
2115
392
|
- `testTimeout: 10000`:单个测试超时 10 秒
|
|
2116
393
|
- `environment: 'node'`:使用 Node.js 测试环境
|
|
2117
394
|
|
|
2118
|
-
###
|
|
395
|
+
### 8.4 安全性
|
|
2119
396
|
|
|
2120
397
|
- 不在日志中记录 Claude Code API 密钥等敏感信息
|
|
2121
398
|
- `--permission-mode bypassPermissions` 仅在 worktree 隔离环境中使用
|