clawt 3.4.6 → 3.5.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/.claude/settings.local.json +12 -0
- package/README.md +0 -4
- package/dist/index.js +583 -314
- package/dist/postinstall.js +37 -2
- package/docs/alias.md +7 -1
- package/docs/completion.md +1 -1
- package/docs/config.md +4 -3
- package/docs/cover-validate.md +4 -3
- package/docs/create.md +28 -12
- package/docs/home.md +12 -8
- package/docs/init.md +16 -9
- package/docs/list.md +13 -7
- package/docs/merge.md +12 -12
- package/docs/remove.md +24 -13
- package/docs/reset.md +6 -4
- package/docs/resume.md +3 -4
- package/docs/status.md +75 -30
- package/docs/sync.md +26 -26
- package/docs/validate.md +13 -7
- package/package.json +1 -1
- package/src/commands/merge.ts +20 -5
- package/src/commands/tasks.ts +51 -0
- package/src/constants/ai-prompts.ts +14 -0
- package/src/constants/config.ts +9 -0
- package/src/constants/index.ts +4 -0
- package/src/constants/interactive-panel.ts +6 -0
- package/src/constants/messages/index.ts +4 -2
- package/src/constants/messages/interactive-panel.ts +12 -0
- package/src/constants/messages/merge.ts +15 -0
- package/src/constants/messages/tasks.ts +9 -0
- package/src/constants/tasks-template.ts +28 -0
- package/src/index.ts +2 -0
- package/src/types/command.ts +8 -0
- package/src/types/config.ts +4 -0
- package/src/types/index.ts +1 -1
- package/src/utils/conflict-resolver.ts +170 -0
- package/src/utils/formatter.ts +19 -0
- package/src/utils/git-branch.ts +116 -0
- package/src/utils/git-core.ts +417 -0
- package/src/utils/git-worktree.ts +40 -0
- package/src/utils/git.ts +3 -521
- package/src/utils/index.ts +7 -2
- package/src/utils/interactive-panel-render.ts +12 -6
- package/src/utils/interactive-panel-state.ts +137 -0
- package/src/utils/interactive-panel.ts +44 -188
- package/src/utils/keyboard-controller.ts +48 -0
- package/src/utils/ui-prompts.ts +240 -0
- package/src/utils/worktree-matcher.ts +21 -251
- package/tests/unit/commands/merge.test.ts +59 -3
- package/tests/unit/commands/tasks.test.ts +153 -0
- package/tests/unit/utils/conflict-resolver.test.ts +250 -0
- package/tests/unit/utils/formatter.test.ts +26 -1
- package/src/constants/messages.ts +0 -179
package/dist/postinstall.js
CHANGED
|
@@ -164,7 +164,22 @@ ${branches.map((b) => ` - ${b}`).join("\n")}`,
|
|
|
164
164
|
/** merge 交互选择提示 */
|
|
165
165
|
MERGE_SELECT_BRANCH: "\u8BF7\u9009\u62E9\u8981\u5408\u5E76\u7684\u5206\u652F",
|
|
166
166
|
/** merge 模糊匹配到多个结果提示 */
|
|
167
|
-
MERGE_MULTIPLE_MATCHES: (name) => `"${name}" \u5339\u914D\u5230\u591A\u4E2A\u5206\u652F\uFF0C\u8BF7\u9009\u62E9\uFF1A
|
|
167
|
+
MERGE_MULTIPLE_MATCHES: (name) => `"${name}" \u5339\u914D\u5230\u591A\u4E2A\u5206\u652F\uFF0C\u8BF7\u9009\u62E9\uFF1A`,
|
|
168
|
+
/** 询问是否使用 AI 辅助解决冲突 */
|
|
169
|
+
MERGE_CONFLICT_ASK_AI: "\u68C0\u6D4B\u5230\u5408\u5E76\u51B2\u7A81\uFF0C\u662F\u5426\u4F7F\u7528 Claude Code \u81EA\u52A8\u89E3\u51B3\uFF1F",
|
|
170
|
+
/** AI 冲突解决开始 */
|
|
171
|
+
MERGE_CONFLICT_AI_START: (fileCount) => `\u6B63\u5728\u4F7F\u7528 Claude Code \u5206\u6790\u5E76\u89E3\u51B3 ${fileCount} \u4E2A\u51B2\u7A81\u6587\u4EF6...`,
|
|
172
|
+
/** AI 冲突解决成功 */
|
|
173
|
+
MERGE_CONFLICT_AI_SUCCESS: "\u2713 Claude Code \u5DF2\u6210\u529F\u89E3\u51B3\u6240\u6709\u51B2\u7A81",
|
|
174
|
+
/** AI 冲突解决后仍有未解决的冲突 */
|
|
175
|
+
MERGE_CONFLICT_AI_PARTIAL: (remaining) => `Claude Code \u5DF2\u5904\u7406\u51B2\u7A81\u6587\u4EF6\uFF0C\u4F46\u4ECD\u6709 ${remaining} \u4E2A\u6587\u4EF6\u5B58\u5728\u51B2\u7A81
|
|
176
|
+
\u8BF7\u624B\u52A8\u5904\u7406\u5269\u4F59\u51B2\u7A81\u540E\u6267\u884C git add . && git merge --continue`,
|
|
177
|
+
/** AI 冲突解决失败 */
|
|
178
|
+
MERGE_CONFLICT_AI_FAILED: (errorMsg) => `Claude Code \u89E3\u51B3\u51B2\u7A81\u5931\u8D25: ${errorMsg}
|
|
179
|
+
\u8BF7\u624B\u52A8\u5904\u7406\uFF1A
|
|
180
|
+
\u89E3\u51B3\u51B2\u7A81\u540E\u6267\u884C git add . && git merge --continue`,
|
|
181
|
+
/** --auto 模式下的冲突手动解决(配置为 manual) */
|
|
182
|
+
MERGE_CONFLICT_MANUAL: "\u5408\u5E76\u5B58\u5728\u51B2\u7A81\uFF0C\u8BF7\u624B\u52A8\u5904\u7406\uFF1A\n \u89E3\u51B3\u51B2\u7A81\u540E\u6267\u884C git add . && git merge --continue"
|
|
168
183
|
};
|
|
169
184
|
|
|
170
185
|
// src/constants/messages/validate.ts
|
|
@@ -490,6 +505,16 @@ var HOME_MESSAGES = {
|
|
|
490
505
|
HOME_SWITCH_SUCCESS: (from, to) => `\u2713 \u5DF2\u4ECE ${from} \u5207\u6362\u5230\u4E3B\u5DE5\u4F5C\u5206\u652F ${to}`
|
|
491
506
|
};
|
|
492
507
|
|
|
508
|
+
// src/constants/messages/tasks.ts
|
|
509
|
+
var TASKS_CMD_MESSAGES = {
|
|
510
|
+
/** 任务模板文件已存在 */
|
|
511
|
+
TASK_INIT_FILE_EXISTS: (path) => `\u6587\u4EF6\u5DF2\u5B58\u5728: ${path}\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u5148\u5220\u9664`,
|
|
512
|
+
/** 任务模板生成成功 */
|
|
513
|
+
TASK_INIT_SUCCESS: (path) => `\u2713 \u4EFB\u52A1\u6A21\u677F\u5DF2\u751F\u6210: ${path}`,
|
|
514
|
+
/** 任务模板使用提示 */
|
|
515
|
+
TASK_INIT_HINT: (path) => `\u4F7F\u7528 clawt run -f ${path} \u6267\u884C\u4EFB\u52A1`
|
|
516
|
+
};
|
|
517
|
+
|
|
493
518
|
// src/constants/messages/interactive-panel.ts
|
|
494
519
|
import chalk from "chalk";
|
|
495
520
|
|
|
@@ -548,7 +573,8 @@ var MESSAGES = {
|
|
|
548
573
|
...COMPLETION_MESSAGES,
|
|
549
574
|
...INIT_MESSAGES,
|
|
550
575
|
...COVER_VALIDATE_MESSAGES,
|
|
551
|
-
...HOME_MESSAGES
|
|
576
|
+
...HOME_MESSAGES,
|
|
577
|
+
...TASKS_CMD_MESSAGES
|
|
552
578
|
};
|
|
553
579
|
|
|
554
580
|
// src/constants/terminal.ts
|
|
@@ -592,6 +618,15 @@ var CONFIG_DEFINITIONS = {
|
|
|
592
618
|
autoUpdate: {
|
|
593
619
|
defaultValue: true,
|
|
594
620
|
description: "\u662F\u5426\u542F\u7528\u81EA\u52A8\u66F4\u65B0\u68C0\u67E5\uFF08\u6BCF 24 \u5C0F\u65F6\u68C0\u67E5\u4E00\u6B21 npm registry\uFF09"
|
|
621
|
+
},
|
|
622
|
+
conflictResolveMode: {
|
|
623
|
+
defaultValue: "ask",
|
|
624
|
+
description: "merge \u51B2\u7A81\u65F6\u7684\u89E3\u51B3\u6A21\u5F0F\uFF1Aask\uFF08\u8BE2\u95EE\u662F\u5426\u4F7F\u7528 AI\uFF09\u3001auto\uFF08\u81EA\u52A8 AI \u89E3\u51B3\uFF09\u3001manual\uFF08\u624B\u52A8\u89E3\u51B3\uFF09",
|
|
625
|
+
allowedValues: ["ask", "auto", "manual"]
|
|
626
|
+
},
|
|
627
|
+
conflictResolveTimeoutMs: {
|
|
628
|
+
defaultValue: 3e5,
|
|
629
|
+
description: "Claude Code \u51B2\u7A81\u89E3\u51B3\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09\uFF0C\u9ED8\u8BA4 300000\uFF085 \u5206\u949F\uFF09"
|
|
595
630
|
}
|
|
596
631
|
};
|
|
597
632
|
function deriveDefaultConfig(definitions) {
|
package/docs/alias.md
CHANGED
|
@@ -31,7 +31,7 @@ clawt alias remove <alias>
|
|
|
31
31
|
|
|
32
32
|
**约束规则:**
|
|
33
33
|
|
|
34
|
-
1. **别名不能覆盖内置命令名**:别名不能与任何已注册的内置命令同名(动态检测,当前包括 `list`、`create`、`remove`、`run`、`resume`、`validate`、`merge`、`config`、`sync`、`reset`、`status`、`alias`、`projects`、`completion`、`init`)。如果用户尝试设置与内置命令同名的别名,输出错误提示并返回
|
|
34
|
+
1. **别名不能覆盖内置命令名**:别名不能与任何已注册的内置命令同名(动态检测,当前包括 `list`、`create`、`remove`、`run`、`resume`、`validate`、`cover`、`merge`、`config`、`sync`、`reset`、`status`、`alias`、`projects`、`completion`、`init`、`home`)。如果用户尝试设置与内置命令同名的别名,输出错误提示并返回
|
|
35
35
|
2. **目标必须是内置命令**:别名的目标(`<command>`)必须是已注册的内置命令名。如果指定了不存在的目标命令,输出错误提示并返回
|
|
36
36
|
3. **参数透传**:通过别名调用时,所有选项和参数会完全透传给目标命令,行为与直接调用目标命令完全一致
|
|
37
37
|
|
|
@@ -105,4 +105,10 @@ clawt alias list
|
|
|
105
105
|
clawt alias remove l
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
+
**实现要点:**
|
|
109
|
+
|
|
110
|
+
- 消息常量定义在 `src/constants/messages/alias.ts`(`ALIAS_MESSAGES`),包括列表为空提示、设置/移除成功、别名不存在、与内置命令冲突、目标命令不存在等消息
|
|
111
|
+
- 别名应用逻辑位于 `src/utils/alias.ts` 的 `applyAliases` 函数:在主入口 `src/index.ts` 中,所有命令注册完成后调用,遍历配置中的 `aliases` 映射,通过 Commander.js 的 `.alias()` 方法为对应命令注册别名。如果目标命令不存在则跳过并输出 warn 级别日志
|
|
112
|
+
- 内置命令冲突检测通过 `getRegisteredCommandNames(program)` 动态获取所有已注册命令名,而非硬编码命令列表
|
|
113
|
+
|
|
108
114
|
---
|
package/docs/completion.md
CHANGED
|
@@ -37,7 +37,7 @@ clawt completion install
|
|
|
37
37
|
| `-f` / `--file` 参数之后 | 动态列出匹配的文件和子目录(不限制文件类型,支持子目录递归浏览) |
|
|
38
38
|
| `config set` / `config get` 之后 | 动态列出所有配置项键名(从 `CONFIG_DEFINITIONS` 获取) |
|
|
39
39
|
| 输入以 `-` 开头 | 列出当前命令层级的可用选项(short/long) |
|
|
40
|
-
| 其他情况 |
|
|
40
|
+
| 其他情况 | 列出当前命令层级的可用子命令及别名;若输入为空,同时列出可用选项 |
|
|
41
41
|
|
|
42
42
|
**文件路径补全细节:**
|
|
43
43
|
- 支持子目录递归浏览(如 `tasks/` 后继续 Tab 可深入子目录)
|
package/docs/config.md
CHANGED
|
@@ -25,7 +25,7 @@ clawt config reset
|
|
|
25
25
|
1. 读取全局配置文件 `~/.clawt/config.json`
|
|
26
26
|
2. 列出所有配置项供用户选择(`Enquirer.Select`),每项显示:
|
|
27
27
|
- 配置项名称
|
|
28
|
-
-
|
|
28
|
+
- 当前值(布尔值绿色/黄色,字符串和数字青色)
|
|
29
29
|
- 配置项描述(暗淡色 dim)
|
|
30
30
|
- 对象类型配置项(如 `aliases`)标灰不可选,提示用户通过专用命令管理
|
|
31
31
|
3. 用户选择某个配置项后,根据值类型自动选择提示策略:
|
|
@@ -86,7 +86,8 @@ clawt config reset
|
|
|
86
86
|
- 配置项类型定义:`ConfigItemDefinition` 新增可选字段 `allowedValues`(`readonly string[]`),仅对 string 类型有效,用于枚举值校验和交互式 Select 提示
|
|
87
87
|
- 值解析与提示策略:`src/utils/config-strategy.ts` 中的 `parseConfigValue()`(CLI 字符串解析)和 `promptConfigValue()`(交互式提示),基于类型和 `allowedValues` 自动分发
|
|
88
88
|
- 交互式配置编辑:`handleInteractiveConfigSet` 调用通用的 `interactiveConfigEditor`(`src/utils/config-strategy.ts`),传入 `CONFIG_DEFINITIONS` 和 `disabledKeys`(对象类型配置项禁用映射),不再在 config 命令中直接构建选择列表和调用 `promptConfigValue`
|
|
89
|
-
- `saveConfig(config)`:`src/utils/config.ts`
|
|
90
|
-
- `formatConfigValue(value)`:支持 boolean(绿色/黄色)和 string/number(青色)的格式化显示。`undefined` / `null` 值显示为暗淡色的 `(未设置)
|
|
89
|
+
- `saveConfig(config)`:`src/utils/config.ts` 中的通用配置写入函数,将完整配置对象持久化到文件
|
|
90
|
+
- `formatConfigValue(value)`:支持 boolean(绿色/黄色)和 string/number(青色)的格式化显示。`undefined` / `null` 值显示为暗淡色的 `(未设置)`
|
|
91
|
+
- 对象类型配置项(如 `aliases`)的显示逻辑在 `interactiveConfigEditor` 的列表构建中处理:通过 `JSON.stringify` 以暗淡色显示值,并标记为不可选(disabled),提示用户通过 `clawt alias` 命令管理
|
|
91
92
|
|
|
92
93
|
---
|
package/docs/cover-validate.md
CHANGED
|
@@ -20,9 +20,10 @@ clawt cover
|
|
|
20
20
|
|
|
21
21
|
##### 步骤 1:前置校验
|
|
22
22
|
|
|
23
|
-
1. **主 worktree
|
|
24
|
-
2.
|
|
25
|
-
3.
|
|
23
|
+
1. **主 worktree 校验**(`requireMainWorktree`)
|
|
24
|
+
2. **HEAD 校验**(`requireHead`)
|
|
25
|
+
3. **项目级配置校验**(`requireProjectConfig`)
|
|
26
|
+
4. **验证分支校验**:当前分支必须以 `clawt-validate-` 开头,否则报错退出
|
|
26
27
|
|
|
27
28
|
##### 步骤 2:查找目标 worktree
|
|
28
29
|
|
package/docs/create.md
CHANGED
|
@@ -10,20 +10,25 @@ clawt create -b <branchName> [-n <count>]
|
|
|
10
10
|
|
|
11
11
|
| 参数 | 必填 | 说明 |
|
|
12
12
|
| ---- | ---- | ----------------------------------------------------- |
|
|
13
|
-
| `-b` | 是 | 分支名 |
|
|
14
|
-
| `-n` | 否 | 需要创建的 worktree 数量,默认 `1` |
|
|
13
|
+
| `-b, --branch` | 是 | 分支名 |
|
|
14
|
+
| `-n, --number` | 否 | 需要创建的 worktree 数量,默认 `1` |
|
|
15
15
|
|
|
16
16
|
**运行流程:**
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
通过 `runPreChecks(PRE_CHECK_CREATE)` 执行统一前置校验,包含以下检查项:
|
|
19
|
+
|
|
20
|
+
1. **主 worktree 校验**(`requireMainWorktree`)(2.1)
|
|
21
|
+
2. **HEAD 存在性校验**(`requireHead`):确保仓库有至少一次 commit
|
|
22
|
+
3. **确保在主工作分支上**(`ensureOnClawtMainWorkBranch`):在创建 worktree 之前,确保当前处于配置的主工作分支(`clawtMainWorkBranch`)上。
|
|
20
23
|
- 如果当前分支**是** `clawtMainWorkBranch`,正常继续
|
|
21
24
|
- 如果当前在**验证分支**(`clawt-validate-` 前缀)上:
|
|
22
25
|
- 验证分支上的修改视为可丢弃的临时状态
|
|
23
26
|
- 如果工作区有未提交更改,自动执行 `git reset --hard HEAD && git clean -fd` 清理;若已干净则跳过清理
|
|
24
27
|
- 然后自动切换到主工作分支,继续创建流程
|
|
25
28
|
- 如果当前在**其他普通分支**上:
|
|
26
|
-
-
|
|
29
|
+
- 首先显示警告:`当前分支 <currentBranch> 与配置的主工作分支 <mainBranch> 不一致,如需更新请执行 clawt init`
|
|
30
|
+
- 然后通过 `confirmAction('是否继续执行?')` 让用户确认是否继续;用户拒绝则抛出"已取消操作"退出
|
|
31
|
+
- 用户确认后,如果工作区有未提交的更改,提供交互式选择(避免将修改意外带到主工作分支上):
|
|
27
32
|
```
|
|
28
33
|
⚠ 当前分支有未提交的更改,请选择处理方式:
|
|
29
34
|
|
|
@@ -33,16 +38,17 @@ clawt create -b <branchName> [-n <count>]
|
|
|
33
38
|
```
|
|
34
39
|
- 选择 reset → 执行 `git reset --hard HEAD && git clean -fd`
|
|
35
40
|
- 选择 stash → 执行 `git add . && git stash push -m "clawt:auto-stash"`
|
|
36
|
-
- 选择 exit →
|
|
37
|
-
-
|
|
41
|
+
- 选择 exit → 抛出错误"用户选择退出,请手动处理工作区更改后重试"
|
|
42
|
+
- 处理完成后再次校验工作区是否干净,不干净则报错"工作区仍然不干净,请手动处理"
|
|
38
43
|
- 执行 `git checkout <clawtMainWorkBranch>`,然后继续创建流程
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
4. **主分支工作区干净校验**(`requireCleanWorkingDir`):确保主工作分支的工作区和暂存区干净,存在未提交更改时报错"主 worktree 有未提交的更改,请先处理"
|
|
45
|
+
5. **创建数量校验**:校验 `-n` 参数必须为正整数,否则报错 `无效的创建数量: "<value>",请输入正整数`
|
|
46
|
+
6. **分支名合法性校验与转换** (2.3)
|
|
47
|
+
7. **分支名存在性校验** (2.4)
|
|
42
48
|
- 若 `n = 1`:校验 `branchName`
|
|
43
49
|
- 若 `n > 1`:校验 `branchName-1` 到 `branchName-n`
|
|
44
50
|
- 所有分支名在创建任何 worktree **之前**完成全部校验
|
|
45
|
-
|
|
51
|
+
8. **批量创建 worktree + 验证分支**
|
|
46
52
|
- 若 `n = 1`:
|
|
47
53
|
```bash
|
|
48
54
|
git worktree add -b <branchName> ~/.clawt/worktrees/<project>/<branchName>
|
|
@@ -58,7 +64,7 @@ clawt create -b <branchName> [-n <count>]
|
|
|
58
64
|
git worktree add -b <branchName>-n ~/.clawt/worktrees/<project>/<branchName>-n
|
|
59
65
|
git branch clawt-validate-<branchName>-n
|
|
60
66
|
```
|
|
61
|
-
|
|
67
|
+
9. **输出创建日志**
|
|
62
68
|
|
|
63
69
|
**输出格式:**
|
|
64
70
|
|
|
@@ -82,4 +88,14 @@ clawt create -b <branchName> [-n <count>]
|
|
|
82
88
|
────────────────────────────────────────
|
|
83
89
|
```
|
|
84
90
|
|
|
91
|
+
**实现要点:**
|
|
92
|
+
|
|
93
|
+
- 前置校验配置定义在 `src/constants/pre-checks.ts` 的 `PRE_CHECK_CREATE` 常量中
|
|
94
|
+
- 分支名清理逻辑在 `src/utils/branch.ts` 的 `sanitizeBranchName` 中
|
|
95
|
+
- 分支名生成逻辑在 `src/utils/branch.ts` 的 `generateBranchNames` 中
|
|
96
|
+
- worktree 批量创建逻辑在 `src/utils/worktree.ts` 的 `createWorktrees` 中
|
|
97
|
+
- 确保在主工作分支的逻辑在 `src/utils/validate-branch.ts` 的 `ensureOnMainWorkBranch` 中
|
|
98
|
+
- 脏工作区交互处理逻辑在 `src/utils/validate-branch.ts` 的 `handleDirtyWorkingDir` 中
|
|
99
|
+
- 相关消息常量定义在 `src/constants/messages/create.ts` 和 `src/constants/messages/common.ts` 中
|
|
100
|
+
|
|
85
101
|
---
|
package/docs/home.md
CHANGED
|
@@ -16,21 +16,24 @@ clawt home
|
|
|
16
16
|
|
|
17
17
|
**运行流程:**
|
|
18
18
|
|
|
19
|
-
1.
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
1. **前置校验**:调用 `runPreChecks` 执行统一前置校验:
|
|
20
|
+
- `requireMainWorktree`:校验当前目录是否在主 worktree 根目录 (2.1)
|
|
21
|
+
- `requireHead`:校验 HEAD 是否存在(仓库至少有一次 commit)
|
|
22
|
+
- `requireProjectConfig`:校验项目配置文件是否存在且合法
|
|
23
|
+
- `requireMainBranchExists`:校验配置中的主工作分支在 git 仓库中是否存在
|
|
24
|
+
2. **获取分支信息**:
|
|
22
25
|
- 通过 `getMainWorkBranch()` 获取主工作分支名
|
|
23
26
|
- 通过 `getCurrentBranch()` 获取当前所在分支名
|
|
24
|
-
|
|
27
|
+
3. **判断是否需要切换**:
|
|
25
28
|
- 当前分支 === 主工作分支 → 输出提示信息,无需切换
|
|
26
29
|
- 当前分支 !== 主工作分支 → 调用 `ensureOnMainWorkBranch()` 执行切换
|
|
27
|
-
|
|
30
|
+
4. **输出结果**
|
|
28
31
|
|
|
29
32
|
**输出格式:**
|
|
30
33
|
|
|
31
34
|
```
|
|
32
35
|
# 已在主工作分支上
|
|
33
|
-
|
|
36
|
+
已在主工作分支 main 上,无需切换
|
|
34
37
|
|
|
35
38
|
# 切换成功
|
|
36
39
|
✓ 已从 clawt-validate-feat-login 切换到主工作分支 main
|
|
@@ -48,7 +51,8 @@ clawt home
|
|
|
48
51
|
**实现要点:**
|
|
49
52
|
|
|
50
53
|
- 命令注册函数 `registerHomeCommand` 位于 `src/commands/home.ts`
|
|
51
|
-
-
|
|
52
|
-
-
|
|
54
|
+
- 前置校验通过 `runPreChecks` 统一调用,传入 `requireMainWorktree`、`requireHead`、`requireProjectConfig`、`requireMainBranchExists` 四项校验
|
|
55
|
+
- 主逻辑依赖 `ensureOnMainWorkBranch`、`getCurrentBranch`、`getMainWorkBranch`、`guardMainWorkBranchExists` 等工具函数
|
|
56
|
+
- `ensureOnMainWorkBranch()` 仅在需要切换时才调用(当前分支不等于主工作分支时)
|
|
53
57
|
|
|
54
58
|
---
|
package/docs/init.md
CHANGED
|
@@ -27,20 +27,24 @@ clawt init show
|
|
|
27
27
|
**运行流程(设置模式):**
|
|
28
28
|
|
|
29
29
|
1. **主 worktree 校验** (2.1)
|
|
30
|
-
2.
|
|
30
|
+
2. **加载现有配置**:尝试读取 `~/.clawt/projects/<projectName>/config.json`(可能为 `null`)
|
|
31
|
+
3. **确定主工作分支名**:
|
|
31
32
|
- 传了 `-b` → 使用指定的分支名
|
|
32
|
-
- 未传 `-b` →
|
|
33
|
-
|
|
34
|
-
- 配置文件不存在 →
|
|
35
|
-
- 配置文件已存在 →
|
|
36
|
-
|
|
33
|
+
- 未传 `-b` → 先验证 HEAD 存在,再使用当前分支名(`git rev-parse --abbrev-ref HEAD`)
|
|
34
|
+
4. **合并并写入项目级配置**:将 `clawtMainWorkBranch` 合并到现有配置并写入 `~/.clawt/projects/<projectName>/config.json`
|
|
35
|
+
- 配置文件不存在 → 创建新配置
|
|
36
|
+
- 配置文件已存在 → 合并现有配置,仅更新 `clawtMainWorkBranch` 字段(保留其他配置项不变)
|
|
37
|
+
5. **输出成功提示**:
|
|
38
|
+
- 已有配置 → `✓ 已将主工作分支从 <旧分支> 更新为 <新分支>`
|
|
39
|
+
- 无已有配置 → `✓ 项目初始化成功,主工作分支设置为: <分支名>`
|
|
37
40
|
|
|
38
41
|
**运行流程(show 模式):**
|
|
39
42
|
|
|
40
43
|
1. **主 worktree 校验** (2.1)
|
|
41
|
-
2.
|
|
44
|
+
2. **项目配置校验**(`requireProjectConfig`):读取 `~/.clawt/projects/<projectName>/config.json`
|
|
42
45
|
- 配置不存在 → 抛出错误 `项目尚未初始化,请先执行 clawt init 设置主工作分支`
|
|
43
|
-
-
|
|
46
|
+
- 配置缺少 `clawtMainWorkBranch` 字段 → 抛出错误 `项目配置缺少主工作分支信息,请重新执行 clawt init 设置主工作分支`
|
|
47
|
+
- 配置存在且合法 → 进入交互式面板
|
|
44
48
|
3. **交互式配置编辑**:调用 `interactiveConfigEditor`(`src/utils/config-strategy.ts`),基于 `PROJECT_CONFIG_DEFINITIONS` 构建配置项列表(详见 [project-config.md](./project-config.md))
|
|
45
49
|
- 列出所有项目配置项,显示名称、当前值和描述
|
|
46
50
|
- 用户选择配置项后,根据值类型自动选择输入方式(与全局配置的交互式编辑逻辑一致)
|
|
@@ -61,9 +65,12 @@ clawt init show
|
|
|
61
65
|
|
|
62
66
|
# show 未初始化(抛出错误)
|
|
63
67
|
项目尚未初始化,请先执行 clawt init 设置主工作分支
|
|
68
|
+
|
|
69
|
+
# show 配置缺少主工作分支字段(抛出错误)
|
|
70
|
+
项目配置缺少主工作分支信息,请重新执行 clawt init 设置主工作分支
|
|
64
71
|
```
|
|
65
72
|
|
|
66
|
-
**重复执行:**
|
|
73
|
+
**重复执行:** 支持重复执行,后一次会合并到现有配置中更新 `clawtMainWorkBranch`,不影响其他配置项。
|
|
67
74
|
|
|
68
75
|
**实现要点:**
|
|
69
76
|
|
package/docs/list.md
CHANGED
|
@@ -16,11 +16,10 @@ clawt list [--json]
|
|
|
16
16
|
|
|
17
17
|
1. **主 worktree 校验** (2.1)
|
|
18
18
|
2. **获取项目名** (2.2)
|
|
19
|
-
3.
|
|
20
|
-
4.
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
- 未指定 → 以文本格式输出
|
|
19
|
+
3. 获取项目的所有 worktree 列表(扫描 `~/.clawt/worktrees/<project>/` 目录,与 `git worktree list` 交叉验证)
|
|
20
|
+
4. 根据 `--json` 选项决定输出格式:
|
|
21
|
+
- 指定 `--json` → 以 JSON 格式输出(仅包含 path 和 branch)
|
|
22
|
+
- 未指定 → 以文本格式输出(包含变更状态信息)
|
|
24
23
|
|
|
25
24
|
**文本输出格式(默认):**
|
|
26
25
|
|
|
@@ -30,9 +29,16 @@ clawt list [--json]
|
|
|
30
29
|
当前项目: main-project
|
|
31
30
|
|
|
32
31
|
~/.clawt/worktrees/main-project/feature-scheme-1 [feature-scheme-1]
|
|
32
|
+
3 个提交 +120 -30 (未提交修改)
|
|
33
|
+
|
|
33
34
|
~/.clawt/worktrees/main-project/feature-scheme-2 [feature-scheme-2]
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
1 个提交 +45 -10
|
|
36
|
+
|
|
37
|
+
~/.clawt/worktrees/main-project/feature-scheme-3 [feature-scheme-3] ← 橙色路径(空闲)
|
|
38
|
+
0 个提交 无变更
|
|
39
|
+
|
|
40
|
+
~/.clawt/worktrees/main-project/bugfix-login [bugfix-login]
|
|
41
|
+
2 个提交 +80 -25
|
|
36
42
|
|
|
37
43
|
共 4 个 worktree
|
|
38
44
|
```
|
package/docs/merge.md
CHANGED
|
@@ -33,26 +33,26 @@ clawt merge [-m <commitMessage>]
|
|
|
33
33
|
- 唯一匹配 → 直接使用
|
|
34
34
|
- 多个匹配 → 通过交互式列表让用户从匹配结果中选择
|
|
35
35
|
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
36
|
-
|
|
36
|
+
4. **主 worktree 状态检测**
|
|
37
37
|
- 执行 `git status --porcelain`
|
|
38
38
|
- 如果有更改:
|
|
39
39
|
- 如果存在该分支的 validate 快照(`~/.clawt/validate-snapshots/<project>/<branchName>.tree`),额外输出警告 `主 worktree 可能存在 validate 残留状态,可先执行 clawt validate -b <branchName> --clean 清理`
|
|
40
40
|
- 提示 `主 worktree 有未提交的更改,请先处理`,退出
|
|
41
41
|
- 无更改 → 继续
|
|
42
|
-
|
|
42
|
+
5. **Squash 检测与执行(auto-save 临时提交压缩)**
|
|
43
43
|
- 通过 `git log HEAD..<branchName> --format=%s` 检查目标分支是否存在以 `AUTO_SAVE_COMMIT_MESSAGE`(`chore: auto-save before sync`)为前缀的 commit
|
|
44
|
-
- **不存在** → 跳过,进入步骤
|
|
44
|
+
- **不存在** → 跳过,进入步骤 6
|
|
45
45
|
- **存在** → 提示用户是否将所有提交压缩为一个:
|
|
46
46
|
```
|
|
47
47
|
检测到 sync 产生的临时提交,是否将所有提交压缩为一个?
|
|
48
48
|
压缩后变更将保留在目标worktree的暂存区,需要重新提交(可使用 Claude Code Cli或其他工具生成提交信息)
|
|
49
49
|
```
|
|
50
|
-
- **用户选择不压缩** → 跳过,进入步骤
|
|
50
|
+
- **用户选择不压缩** → 跳过,进入步骤 6
|
|
51
51
|
- **用户选择压缩** →
|
|
52
52
|
1. 获取主分支名(从项目级配置 `clawtMainWorkBranch` 获取)
|
|
53
53
|
2. 计算分叉点:`git merge-base <mainBranch> <branchName>`
|
|
54
54
|
3. 在目标 worktree 中执行 `git reset --soft <merge-base>`,将所有 commit 撤销到暂存区
|
|
55
|
-
4. 如果用户提供了 `-m` → 直接在目标 worktree 执行 `git commit -m '<commitMessage>'`,输出成功提示,继续步骤
|
|
55
|
+
4. 如果用户提供了 `-m` → 直接在目标 worktree 执行 `git commit -m '<commitMessage>'`,输出成功提示,继续步骤 6
|
|
56
56
|
5. 如果用户未提供 `-m` → 提示用户前往目标 worktree 自行提交后重新执行 `clawt merge`:
|
|
57
57
|
```
|
|
58
58
|
✓ 已将所有提交压缩到暂存区
|
|
@@ -61,7 +61,7 @@ clawt merge [-m <commitMessage>]
|
|
|
61
61
|
提交完成后执行:clawt merge -b <branch>
|
|
62
62
|
```
|
|
63
63
|
**退出流程**
|
|
64
|
-
|
|
64
|
+
6. **根据目标 worktree 状态决定是否需要提交**
|
|
65
65
|
- 检测目标 worktree 工作区是否干净(`git status --porcelain`)
|
|
66
66
|
- **工作区有未提交修改**:
|
|
67
67
|
- 如果用户未提供 `-m`,提示 `<worktreePath> 有未提交的修改,请通过 -m 参数提供提交信息`(其中 `<worktreePath>` 为目标 worktree 的完整路径),退出
|
|
@@ -75,23 +75,23 @@ clawt merge [-m <commitMessage>]
|
|
|
75
75
|
- 检查目标分支相对于主分支是否有本地提交(`git log HEAD..<branchName> --oneline`)
|
|
76
76
|
- 有本地提交 → 跳过提交步骤,直接进入合并
|
|
77
77
|
- 无本地提交 → 提示 `目标 worktree 没有任何可合并的变更(工作区干净且无本地提交)`,退出
|
|
78
|
-
|
|
78
|
+
7. **回到主 worktree 进行合并**
|
|
79
79
|
```bash
|
|
80
80
|
cd <主 worktree 路径>
|
|
81
81
|
git merge <branchName>
|
|
82
82
|
```
|
|
83
|
-
|
|
83
|
+
8. **冲突检测**(双层机制)
|
|
84
84
|
- **try-catch 层**:`git merge` 抛出异常时,先检查是否有冲突,有冲突则报错退出,否则重新抛出原始异常
|
|
85
85
|
- **二次确认层**:即使 merge 未抛异常,也再次检查是否有合并冲突
|
|
86
86
|
- **有冲突** → 提示 `合并存在冲突,请手动处理:\n 解决冲突后执行 git add . && git merge --continue`,退出
|
|
87
87
|
- **无冲突** → 继续
|
|
88
|
-
|
|
88
|
+
9. **推送(受 `autoPullPush` 配置控制)**
|
|
89
89
|
- `autoPullPush` 为 `false` → 输出提示 `已跳过自动 pull/push,请手动执行 git pull && git push`
|
|
90
90
|
- `autoPullPush` 为 `true` → 执行 `git pull` + `git push`:
|
|
91
91
|
- `git pull` 失败且有冲突 → 输出警告 `自动 pull 时发生冲突,merge 已完成但远程同步失败`,退出(不再 push)
|
|
92
92
|
- `git pull` 失败且无冲突 → 抛出错误
|
|
93
93
|
- `git push` 失败 → 输出警告 `自动 push 失败,merge 和 pull 已完成\n 请手动执行 git push`,退出
|
|
94
|
-
|
|
94
|
+
10. **输出成功提示**
|
|
95
95
|
|
|
96
96
|
```
|
|
97
97
|
# 提供了 -m 且已推送时
|
|
@@ -111,7 +111,7 @@ clawt merge [-m <commitMessage>]
|
|
|
111
111
|
✓ 分支 feature-scheme-1 已成功合并到当前分支
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
11. **merge 成功后确认并清理 worktree 和分支(可选)**
|
|
115
115
|
- 如果配置文件中 `autoDeleteBranch` 为 `true`,自动执行清理
|
|
116
116
|
- 否则交互式询问用户是否清理
|
|
117
117
|
- 用户确认后,依次执行:
|
|
@@ -129,7 +129,7 @@ clawt merge [-m <commitMessage>]
|
|
|
129
129
|
- 输出清理成功提示:`✓ 已清理 worktree 和分支: <branchName>`
|
|
130
130
|
- 验证分支的删除时机与目标分支保持一致(见 [2.5 验证分支生命周期](#25-验证分支)):用户确认清理 → 同步删除验证分支;用户拒绝清理 → 验证分支也保留
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
12. **清理 validate 快照**
|
|
133
133
|
- merge 成功后,如果存在该分支的 validate 快照(`~/.clawt/validate-snapshots/<project>/<branchName>.tree` 和 `<branchName>.head`),自动删除这些快照文件(merge 成功后快照已无意义)
|
|
134
134
|
|
|
135
135
|
> **注意:** 清理确认和清理操作均在 merge 成功后执行。只有 merge 成功才会询问用户是否清理 worktree 和分支,避免 merge 冲突时用户被提前询问造成困惑。
|
package/docs/remove.md
CHANGED
|
@@ -24,7 +24,10 @@ clawt remove
|
|
|
24
24
|
|
|
25
25
|
**运行流程:**
|
|
26
26
|
|
|
27
|
-
1.
|
|
27
|
+
1. **前置校验**:
|
|
28
|
+
- 主 worktree 校验 (2.1)
|
|
29
|
+
- HEAD 存在性校验
|
|
30
|
+
- 项目配置文件校验(确保项目已通过 `clawt init` 初始化)
|
|
28
31
|
2. **获取项目名** (2.2)
|
|
29
32
|
3. **确定待移除的 worktree 列表**:
|
|
30
33
|
- **指定 `--all`** → 选中当前项目所有 worktree(若当前项目无 worktree,则提示并退出)
|
|
@@ -39,7 +42,8 @@ clawt remove
|
|
|
39
42
|
- 唯一匹配 → 直接使用
|
|
40
43
|
- 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
|
|
41
44
|
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
42
|
-
4.
|
|
45
|
+
4. **当前分支安全检查**:逐个检查待移除的分支,如果该分支或其对应的验证分支(`clawt-validate-<branchName>`)是主 worktree 当前所在分支,则抛出错误并阻止移除。
|
|
46
|
+
5. 列出即将移除的 worktree 及对应分支:
|
|
43
47
|
|
|
44
48
|
```
|
|
45
49
|
即将移除以下 worktree 及本地分支:
|
|
@@ -51,29 +55,36 @@ clawt remove
|
|
|
51
55
|
是否同时删除对应的本地分支和验证分支?(y/N)
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
6. **判断是否删除本地分支**:
|
|
59
|
+
- 如果配置文件 `~/.clawt/config.json` 中 `autoDeleteBranch` 为 `true`,则跳过询问,直接删除分支
|
|
60
|
+
- 否则询问用户是否删除,用户拒绝时提示可稍后手动删除
|
|
61
|
+
7. 对每个 worktree 依次执行(单个失败不影响其他):
|
|
55
62
|
|
|
56
63
|
```bash
|
|
57
|
-
# 确保当前处于主工作分支上(若不在则自动切回)
|
|
58
|
-
git checkout <clawtMainWorkBranch>
|
|
59
|
-
|
|
60
64
|
# 移除 worktree
|
|
61
65
|
git worktree remove -f <worktree路径>
|
|
62
66
|
|
|
63
|
-
#
|
|
67
|
+
# 如果用户选择了删除分支(或 autoDeleteBranch 为 true)
|
|
64
68
|
git branch -D <branchName>
|
|
65
69
|
|
|
66
|
-
#
|
|
70
|
+
# 无条件删除验证分支(不受用户确认控制,存在则删除)
|
|
67
71
|
git branch -D clawt-validate-<branchName>
|
|
68
|
-
#
|
|
72
|
+
# 无条件清理该分支对应的 validate 快照
|
|
69
73
|
```
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
8. 如果使用 `--all` 模式,额外清理整个项目的 validate 快照目录。
|
|
76
|
+
|
|
77
|
+
9. 移除完成后执行清理:
|
|
78
|
+
- `git worktree prune` 清理已失效的 worktree 引用
|
|
79
|
+
- 如果 `~/.clawt/worktrees/<project>/` 下已无 worktree,则删除该项目目录
|
|
72
80
|
|
|
73
|
-
|
|
81
|
+
10. 批量移除时,单个 worktree 移除失败不会中断整个流程,而是收集所有失败项,最后汇总报告并以错误状态退出(抛出 ClawtError)。
|
|
74
82
|
|
|
75
|
-
|
|
83
|
+
**实现要点:**
|
|
76
84
|
|
|
77
|
-
|
|
85
|
+
- 消息常量定义在 `src/constants/messages/remove.ts`
|
|
86
|
+
- 分支解析逻辑复用公共模块 `resolveTargetWorktrees`(`src/utils/worktree-matcher.ts`)
|
|
87
|
+
- 验证分支删除通过 `deleteValidateBranch`(`src/utils/validate-branch.ts`),内部判断分支是否存在后才执行删除
|
|
88
|
+
- 快照清理通过 `removeSnapshot` 和 `removeProjectSnapshots`(`src/utils/validate-snapshot.ts`)
|
|
78
89
|
|
|
79
90
|
---
|
package/docs/reset.md
CHANGED
|
@@ -16,12 +16,14 @@ clawt reset
|
|
|
16
16
|
|
|
17
17
|
**运行流程:**
|
|
18
18
|
|
|
19
|
-
1.
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
1. **前置校验**(`runPreChecks`):
|
|
20
|
+
- `requireMainWorktree`:主 worktree 校验 (2.1)
|
|
21
|
+
- `requireHead`:HEAD 存在校验
|
|
22
|
+
- `requireProjectConfig`:项目级配置校验
|
|
23
|
+
2. **检测工作区状态**:通过 `git status --porcelain` 检测主 worktree 是否有未提交的更改
|
|
22
24
|
- **工作区干净** → 输出提示 `主 worktree 工作区和暂存区已是干净状态,无需重置`,退出
|
|
23
25
|
- **工作区不干净** → 继续
|
|
24
|
-
3. **确认破坏性操作**:如果配置项 `confirmDestructiveOps` 为 `true
|
|
26
|
+
3. **确认破坏性操作**:如果配置项 `confirmDestructiveOps` 为 `true`,提示确认(显示即将执行的危险指令 `git reset --hard + git clean -fd` 和操作后果 `丢弃所有未提交的更改`),用户取消则输出 `已取消操作` 并退出
|
|
25
27
|
4. **重置工作区和暂存区**:
|
|
26
28
|
```bash
|
|
27
29
|
git reset --hard HEAD
|
package/docs/resume.md
CHANGED
|
@@ -22,9 +22,8 @@ clawt resume
|
|
|
22
22
|
|
|
23
23
|
**运行流程:**
|
|
24
24
|
|
|
25
|
-
1.
|
|
26
|
-
2.
|
|
27
|
-
3. **解析目标 worktree**:根据是否传入 `-b` 参数以及 worktree 数量,采用不同的解析策略:
|
|
25
|
+
1. **前置校验**(`PRE_CHECK_RESUME`):主 worktree 校验 (2.1) + HEAD 存在性校验 + Claude Code CLI 可用性校验
|
|
26
|
+
2. **解析目标 worktree**:根据是否传入 `-b` 参数以及 worktree 数量,采用不同的解析策略:
|
|
28
27
|
- **未传 `-b` 参数**:
|
|
29
28
|
- 获取当前项目所有 worktree
|
|
30
29
|
- 无可用 worktree → 报错退出
|
|
@@ -36,7 +35,7 @@ clawt resume
|
|
|
36
35
|
- 唯一匹配 → 直接使用
|
|
37
36
|
- 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
|
|
38
37
|
3. **无匹配** → 报错退出,并列出所有可用分支名
|
|
39
|
-
|
|
38
|
+
3. **根据选中数量自动分发**:
|
|
40
39
|
- **用户未选择任何分支** → 直接退出
|
|
41
40
|
- **选中 1 个** → 根据全局配置项 `resumeInPlace` 决定打开方式:
|
|
42
41
|
- `resumeInPlace: true` → 在当前终端就地恢复,通过 `launchInteractiveClaude()` 启动(使用 `spawnSync` + `inherit stdio`)
|