clawt 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.claude/agents/docs-sync-updater.md +44 -24
  2. package/.clawt/postCreate.sh +2 -0
  3. package/CLAUDE.md +10 -0
  4. package/README.md +50 -2
  5. package/dist/index.js +180 -29
  6. package/dist/postinstall.js +33 -1
  7. package/docs/alias.md +114 -0
  8. package/docs/completion.md +55 -0
  9. package/docs/config-file.md +49 -0
  10. package/docs/config.md +93 -0
  11. package/docs/cover-validate.md +94 -0
  12. package/docs/create.md +105 -0
  13. package/docs/home.md +70 -0
  14. package/docs/init.md +89 -0
  15. package/docs/list.md +73 -0
  16. package/docs/log.md +67 -0
  17. package/docs/merge.md +152 -0
  18. package/docs/notification.md +94 -0
  19. package/docs/post-create-hook.md +142 -0
  20. package/docs/project-config.md +139 -0
  21. package/docs/projects.md +135 -0
  22. package/docs/remove.md +90 -0
  23. package/docs/reset.md +37 -0
  24. package/docs/resume.md +132 -0
  25. package/docs/run.md +150 -0
  26. package/docs/spec.md +431 -0
  27. package/docs/status.md +345 -0
  28. package/docs/sync.md +128 -0
  29. package/docs/tasks.md +74 -0
  30. package/docs/update-check.md +95 -0
  31. package/docs/validate.md +416 -0
  32. package/package.json +1 -1
  33. package/src/commands/create.ts +5 -0
  34. package/src/commands/run.ts +12 -0
  35. package/src/constants/config.ts +1 -1
  36. package/src/constants/git.ts +3 -0
  37. package/src/constants/messages/index.ts +2 -0
  38. package/src/constants/messages/post-create.ts +29 -0
  39. package/src/constants/project-config.ts +4 -0
  40. package/src/hooks/index.ts +1 -0
  41. package/src/hooks/post-create.ts +198 -0
  42. package/src/types/command.ts +4 -0
  43. package/src/types/index.ts +1 -0
  44. package/src/types/postCreateHook.ts +24 -0
  45. package/src/types/projectConfig.ts +3 -1
  46. package/src/utils/claude.ts +2 -1
  47. package/src/utils/git-core.ts +4 -0
  48. package/src/utils/index.ts +1 -0
  49. package/src/utils/shell.ts +3 -0
  50. package/src/utils/task-executor.ts +5 -1
  51. package/tests/unit/commands/create.test.ts +1 -0
  52. package/tests/unit/commands/run.test.ts +1 -0
  53. package/tests/unit/constants/messages-post-create.test.ts +112 -0
  54. package/tests/unit/hooks/post-create.test.ts +434 -0
  55. package/tests/unit/utils/claude.test.ts +76 -1
package/docs/remove.md ADDED
@@ -0,0 +1,90 @@
1
+ ### 5.5 移除 Worktree
2
+
3
+ **命令:**
4
+
5
+ ```bash
6
+ # 移除当前项目所有 worktree
7
+ clawt remove --all
8
+
9
+ # 指定分支名(支持模糊匹配)
10
+ clawt remove -b <branchName>
11
+
12
+ # 不指定参数(列出所有分支供多选)
13
+ clawt remove
14
+ ```
15
+
16
+ **参数:**
17
+
18
+ | 参数 | 必填 | 说明 |
19
+ | --------- | ---- | ---------------------------------------------------------------------- |
20
+ | `--all` | 否 | 移除当前项目 (`~/.clawt/worktrees/<project>/`) 下所有 worktree |
21
+ | `-b` | 否 | 指定分支名(支持模糊匹配,不传则列出所有分支供多选) |
22
+
23
+ > **提示:** 不传 `--all` 也不传 `-b` 时,会列出当前项目所有 worktree 供交互式多选。
24
+
25
+ **运行流程:**
26
+
27
+ 1. **前置校验**:
28
+ - 主 worktree 校验 (2.1)
29
+ - HEAD 存在性校验
30
+ - 项目配置文件校验(确保项目已通过 `clawt init` 初始化)
31
+ 2. **获取项目名** (2.2)
32
+ 3. **确定待移除的 worktree 列表**:
33
+ - **指定 `--all`** → 选中当前项目所有 worktree(若当前项目无 worktree,则提示并退出)
34
+ - **未指定 `--all`** → 通过 `resolveTargetWorktrees` 解析目标 worktree(多选版本),匹配策略如下:
35
+ - **未传 `-b` 参数**:
36
+ - 无可用 worktree → 报错退出
37
+ - 仅 1 个 worktree → 直接使用,无需选择
38
+ - 多个 worktree → 通过交互式多选列表(Enquirer.MultiSelect)让用户选择(空格选择,回车确认)
39
+ - **传了 `-b` 参数**:
40
+ 1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
41
+ 2. **模糊匹配**(子串匹配,大小写不敏感):
42
+ - 唯一匹配 → 直接使用
43
+ - 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
44
+ 3. **无匹配** → 报错退出,并列出所有可用分支名
45
+ 4. **当前分支安全检查**:逐个检查待移除的分支,如果该分支或其对应的验证分支(`clawt-validate-<branchName>`)是主 worktree 当前所在分支,则抛出错误并阻止移除。
46
+ 5. 列出即将移除的 worktree 及对应分支:
47
+
48
+ ```
49
+ 即将移除以下 worktree 及本地分支:
50
+
51
+ 1. ~/.clawt/worktrees/main-project/feature-scheme-1 → 分支: feature-scheme-1 验证分支: clawt-validate-feature-scheme-1
52
+ 2. ~/.clawt/worktrees/main-project/feature-scheme-2 → 分支: feature-scheme-2 验证分支: clawt-validate-feature-scheme-2
53
+ 3. ~/.clawt/worktrees/main-project/feature-scheme-3 → 分支: feature-scheme-3 验证分支: clawt-validate-feature-scheme-3
54
+
55
+ 是否同时删除对应的本地分支和验证分支?(y/N)
56
+ ```
57
+
58
+ 6. **判断是否删除本地分支**:
59
+ - 如果配置文件 `~/.clawt/config.json` 中 `autoDeleteBranch` 为 `true`,则跳过询问,直接删除分支
60
+ - 否则询问用户是否删除,用户拒绝时提示可稍后手动删除
61
+ 7. 对每个 worktree 依次执行(单个失败不影响其他):
62
+
63
+ ```bash
64
+ # 移除 worktree
65
+ git worktree remove -f <worktree路径>
66
+
67
+ # 如果用户选择了删除分支(或 autoDeleteBranch 为 true)
68
+ git branch -D <branchName>
69
+
70
+ # 无条件删除验证分支(不受用户确认控制,存在则删除)
71
+ git branch -D clawt-validate-<branchName>
72
+ # 无条件清理该分支对应的 validate 快照
73
+ ```
74
+
75
+ 8. 如果使用 `--all` 模式,额外清理整个项目的 validate 快照目录。
76
+
77
+ 9. 移除完成后执行清理:
78
+ - `git worktree prune` 清理已失效的 worktree 引用
79
+ - 如果 `~/.clawt/worktrees/<project>/` 下已无 worktree,则删除该项目目录
80
+
81
+ 10. 批量移除时,单个 worktree 移除失败不会中断整个流程,而是收集所有失败项,最后汇总报告并以错误状态退出(抛出 ClawtError)。
82
+
83
+ **实现要点:**
84
+
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`)
89
+
90
+ ---
package/docs/reset.md ADDED
@@ -0,0 +1,37 @@
1
+ ### 5.13 重置主 Worktree 工作区和暂存区
2
+
3
+ **命令:**
4
+
5
+ ```bash
6
+ clawt reset
7
+ ```
8
+
9
+ **无参数。**
10
+
11
+ **使用场景:**
12
+
13
+ 当用户通过 `clawt validate` 将分支变更迁移到主 worktree 后,希望快速清除工作区和暂存区的所有修改,恢复到干净状态。与 `clawt validate --clean` 的区别在于:`reset` 仅重置工作区和暂存区,**不删除** validate 快照文件,也**不切换分支**,适用于只想清空变更而保留快照以便后续增量 validate 的场景。
14
+
15
+ > **设计原因**:reset 的职责是「重置工作区状态」,分支切换属于 validate --clean 和 remove 等命令的职责。将分支切换耦合到 reset 会违反单一职责原则。
16
+
17
+ **运行流程:**
18
+
19
+ 1. **前置校验**(`runPreChecks`):
20
+ - `requireMainWorktree`:主 worktree 校验 (2.1)
21
+ - `requireHead`:HEAD 存在校验
22
+ - `requireProjectConfig`:项目级配置校验
23
+ 2. **检测工作区状态**:通过 `git status --porcelain` 检测主 worktree 是否有未提交的更改
24
+ - **工作区干净** → 输出提示 `主 worktree 工作区和暂存区已是干净状态,无需重置`,退出
25
+ - **工作区不干净** → 继续
26
+ 3. **确认破坏性操作**:如果配置项 `confirmDestructiveOps` 为 `true`,提示确认(显示即将执行的危险指令 `git reset --hard + git clean -fd` 和操作后果 `丢弃所有未提交的更改`),用户取消则输出 `已取消操作` 并退出
27
+ 4. **重置工作区和暂存区**:
28
+ ```bash
29
+ git reset --hard HEAD
30
+ git clean -fd
31
+ ```
32
+ 5. **输出成功提示**:
33
+ ```
34
+ ✓ 主 worktree 工作区和暂存区已重置
35
+ ```
36
+
37
+ ---
package/docs/resume.md ADDED
@@ -0,0 +1,132 @@
1
+ ### 5.11 在已有 Worktree 中恢复会话
2
+
3
+ **命令:**
4
+
5
+ ```bash
6
+ # 指定分支名(支持模糊匹配)
7
+ clawt resume -b <branchName>
8
+
9
+ # 不指定分支名(列出所有分支供多选)
10
+ clawt resume
11
+
12
+ # 非交互式追问(指定分支 + 追问内容)
13
+ clawt resume -b <branchName> --prompt "追问内容"
14
+
15
+ # 从任务文件批量追问(通过 branch 名匹配已有 worktree)
16
+ clawt resume -f tasks.md
17
+
18
+ # 批量追问时限制并发数
19
+ clawt resume -f tasks.md -c 2
20
+ ```
21
+
22
+ **参数:**
23
+
24
+ | 参数 | 必填 | 说明 |
25
+ | ---- | ---- | ----------------------------------------------------- |
26
+ | `-b` | 否 | 要恢复的分支名(支持模糊匹配,不传则列出所有分支供多选) |
27
+ | `--prompt` | 否 | 非交互式追问内容(需配合 `-b` 指定分支,与 `-f` 互斥) |
28
+ | `-f, --file` | 否 | 从任务文件批量追问(通过 branch 名匹配已有 worktree,与 `--prompt` 互斥) |
29
+ | `-c, --concurrency` | 否 | 批量追问最大并发数,`0` 表示不限制 |
30
+
31
+ **使用场景:**
32
+
33
+ 当用户之前通过 `clawt run` 或 `clawt create` 创建了 worktree 但会话已结束,希望在该 worktree 中重新打开 Claude Code 交互式界面继续工作。支持一次选中多个分支,自动在独立终端 Tab 中批量恢复。
34
+
35
+ 此外还支持**非交互式追问模式**:通过 `--prompt` 对指定分支进行追问,或通过 `-f` 从任务文件批量追问多个分支。追问模式下会自动检测是否有历史会话,有则追加 `--continue` 继续上次对话。
36
+
37
+ **互斥约束:**
38
+
39
+ - `--prompt` 和 `-f` **不能同时使用**
40
+ - `--prompt` 必须配合 `-b` 指定分支
41
+
42
+ **运行流程:**
43
+
44
+ 1. **前置校验**(`PRE_CHECK_RESUME`):主 worktree 校验 (2.1) + HEAD 存在性校验 + Claude Code CLI 可用性校验
45
+ 2. **非交互式追问分支**:
46
+ - **`--prompt` 和 `-f` 互斥校验**:两者同时传入则报错退出
47
+ - **`--prompt` 模式**(单分支追问):
48
+ - 必须配合 `-b` 指定分支,否则报错退出
49
+ - 通过精确匹配查找目标 worktree,找不到则列出可用分支报错
50
+ - 检查目标 worktree 是否有历史会话,有则追加 `--continue`
51
+ - 调用 `executeBatchTasks` 执行单任务追问
52
+ - **`-f` 模式**(批量追问):
53
+ - 从任务文件解析追问条目(branch 为必填字段)
54
+ - 按 branch 名精确匹配已有 worktree,构建执行参数
55
+ - 按 worktree 独立检查是否有历史会话
56
+ - 解析并发数(`-c` 参数 > 全局配置 `maxConcurrency`)
57
+ - 调用 `executeBatchTasks` 批量执行追问
58
+ 3. **交互式恢复逻辑**(未传 `--prompt` 和 `-f` 时):解析目标 worktree:根据是否传入 `-b` 参数以及 worktree 数量,采用不同的解析策略:
59
+ - **未传 `-b` 参数**:
60
+ - 获取当前项目所有 worktree
61
+ - 无可用 worktree → 报错退出
62
+ - 仅 1 个 worktree → 通过 `resolveTargetWorktrees` 直接使用,无需选择
63
+ - 多个 worktree → 通过 `promptGroupedMultiSelectBranches` 展示**按日期分组的交互式多选列表**(详见下文「按日期分组多选」)
64
+ - **传了 `-b` 参数**:通过 `resolveTargetWorktrees` 解析,匹配策略如下:
65
+ 1. **精确匹配优先**:在 worktree 列表中查找分支名完全相同的 worktree,找到则直接使用
66
+ 2. **模糊匹配**(子串匹配,大小写不敏感):
67
+ - 唯一匹配 → 直接使用
68
+ - 多个匹配 → 通过交互式多选列表让用户从匹配结果中选择
69
+ 3. **无匹配** → 报错退出,并列出所有可用分支名
70
+ 3. **根据选中数量自动分发**:
71
+ - **用户未选择任何分支** → 直接退出
72
+ - **选中 1 个** → 根据全局配置项 `resumeInPlace` 决定打开方式:
73
+ - `resumeInPlace: true` → 在当前终端就地恢复,通过 `launchInteractiveClaude()` 启动(使用 `spawnSync` + `inherit stdio`)
74
+ - `resumeInPlace: false`(默认) → 通过 `launchInteractiveClaudeInNewTerminal()` 在新终端 Tab 中恢复,终端类型由 `terminalApp` 配置控制
75
+ - **选中多个** → 进入批量恢复流程(见下文),始终在新终端 Tab 中打开,不受 `resumeInPlace` 影响
76
+
77
+ **批量恢复流程:**
78
+
79
+ 1. **计算会话状态**:一次性遍历所有选中的 worktree,通过 `hasClaudeSessionHistory()` 检测是否存在历史会话,构建 sessionMap 避免重复 I/O
80
+ 2. **输出预览**:列出即将恢复的分支及其会话状态("继续上次对话"或"新对话")
81
+ 3. **用户确认**:提示即将在 N 个独立终端 Tab 中恢复会话,等待用户确认
82
+ 4. **逐个在新终端 Tab 中启动**:通过 `launchInteractiveClaudeInNewTerminal()` 构建 shell 命令并通过 AppleScript 在新终端 Tab 中执行
83
+ 5. **输出完成提示**
84
+
85
+ **终端 Tab 管理:**
86
+
87
+ 批量恢复通过 `openCommandInNewTerminalTab()`(`src/utils/terminal.ts`)在新终端 Tab 中启动 Claude Code。终端类型由配置项 `terminalApp` 控制:
88
+
89
+ | 配置值 | 行为 |
90
+ | ---------- | ------------------------------------------------------------ |
91
+ | `auto` | 自动检测:优先检测 iTerm2 是否已安装(`/Applications/iTerm.app`),已安装则使用 iTerm2,否则降级到 Terminal.app |
92
+ | `iterm2` | 强制使用 iTerm2 |
93
+ | `terminal` | 强制使用 Terminal.app |
94
+
95
+ **平台限制:** 批量恢复目前仅支持 macOS 平台(通过 AppleScript 打开终端 Tab)。非 macOS 平台会抛出错误。
96
+
97
+ **权限要求:** Terminal.app 通过 System Events 模拟键盘操作(`Cmd+T`)新建 Tab,需要在「系统设置 → 隐私与安全性 → 辅助功能」中授权终端应用。iTerm2 使用原生 AppleScript 接口,无需辅助功能权限。
98
+
99
+ 启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,与 `clawt run` 不传 `--tasks` 时的交互式界面行为一致。
100
+
101
+ **按日期分组多选:**
102
+
103
+ 当未传 `-b` 且有多个 worktree 时,使用 `promptGroupedMultiSelectBranches` 展示按创建日期分组的交互式多选列表,实现流程如下:
104
+
105
+ 1. **日期分组**(`groupWorktreesByDate`):通过 `statSync` 获取各 worktree 目录的文件系统创建时间(`birthtime`),按本地时区格式化为 `YYYY-MM-DD` 作为分组键。无法获取创建时间的分支归入「未知日期」组。分组按日期降序排列,未知日期组在最后。
106
+ 2. **构建选项列表**(`buildGroupedChoices`):生成包含以下元素的 Enquirer MultiSelect choices 数组:
107
+ - 顶部:全局全选选项 `[select-all]`
108
+ - 每组:日期分隔线(显示日期和相对时间,如「2026-02-26(昨天)」)→ 组级全选选项 `[select-all: YYYY-MM-DD]` → 该组内各分支
109
+ 2.5. **构建组成员映射**(`buildGroupMembershipMap`):生成"组全选 name → 该组分支 name 列表"的 Map,供三级联动的 `space()` 方法快速查找某个组全选项对应的所有分支
110
+ 3. **三级联动选择**:通过继承 Enquirer MultiSelect 并覆写 `space()` 方法实现,同步逻辑由 `syncGlobalSelectAll` 和 `syncGroupSelectAll` 两个内部函数负责:
111
+ - **全局全选**:toggle 所有 choices(含组全选)
112
+ - **组级全选**:toggle 该组内所有分支,并同步全局全选状态
113
+ - **普通分支**:toggle 该分支,同步所属组全选和全局全选状态
114
+ 4. **过滤结果**:返回时过滤掉全选项和组全选项,只返回实际选中的 worktree
115
+
116
+ 相对日期显示规则:`formatRelativeDate` 基于自然日差值计算——今天 / 昨天 / N 天前 / N 个月前 / N 年前。
117
+
118
+ 相关常量定义在 `src/constants/prompt.ts`:
119
+
120
+ | 常量 | 说明 |
121
+ | ---- | ---- |
122
+ | `GROUP_SELECT_ALL_PREFIX` | 组级全选选项的 name 前缀(`__group_select_all_`) |
123
+ | `GROUP_SELECT_ALL_LABEL(dateLabel)` | 生成组级全选选项的显示文本 |
124
+ | `GROUP_SEPARATOR_LABEL(dateLabel, relativeTime)` | 生成日期分隔线的显示文本(含 chalk 高亮) |
125
+ | `UNKNOWN_DATE_GROUP` | 无法获取创建日期时的默认分组名称(`未知日期`) |
126
+ | `UNKNOWN_DATE_SEPARATOR_LABEL` | 未知日期分组的分隔线显示文本 |
127
+ | `SELECT_ALL_NAME` | 全局全选选项的标识名称(`__select_all__`) |
128
+ | `SELECT_ALL_LABEL` | 全局全选选项的显示文本(`[select-all]`) |
129
+
130
+ **会话自动续接:** 启动前会自动检测该 worktree 是否存在 Claude Code 历史会话(通过检查 `~/.claude/projects/<encoded-path>/` 下是否有 `.jsonl` 文件判断),如果存在则自动追加 `--continue` 参数继续上次对话,否则打开新对话。启动信息中会显示当前模式("继续上次对话"或"新对话")。路径编码规则:将绝对路径中所有非字母数字字符替换为 `-`(与 Claude Code 源码的编码逻辑一致)。
131
+
132
+ ---
package/docs/run.md ADDED
@@ -0,0 +1,150 @@
1
+ ### 5.2 批量创建 Worktree + 执行 Claude Code 任务
2
+
3
+ > **注意:** run 命令内部调用 `createWorktrees` 或 `createWorktreesByBranches`,因此验证分支的创建和主工作分支检测逻辑(包括工作区脏状态处理)**自动继承** create 命令的变更,无需额外修改 run 命令本身。
4
+
5
+ **命令:**
6
+
7
+ ```bash
8
+ # 方式一:通过 --tasks 参数直接指定任务(多任务并行,支持 variadic 语法)
9
+ clawt run -b <branchName> --tasks <task1> <task2> <task3>
10
+
11
+ # 方式二:通过 -f 从任务文件读取任务列表
12
+ clawt run -f <path>
13
+
14
+ # 方式三:不传 --tasks 也不传 -f,在 worktree 中打开 Claude Code 交互式界面
15
+ clawt run -b <branchName>
16
+ ```
17
+
18
+ **参数:**
19
+
20
+ | 参数 | 必填 | 说明 |
21
+ | --------- | ---- | ----------------------------------------------------------- |
22
+ | `-b` | 否 | 分支名(使用 `-f` 时可选,否则必填) |
23
+ | `--tasks` | 否 | 任务描述(可多次指定,每个 --tasks 对应一个任务,任务数量即 worktree 数量)。不传则在 worktree 中打开 Claude Code 交互式界面 |
24
+ | `-f` | 否 | 从任务文件读取任务列表(与 `--tasks` 互斥) |
25
+ | `-c` | 否 | 最大并发数,`0` 表示不限制 |
26
+ | `--dry-run` | 否 | 试运行模式,仅输出预览信息不实际执行 |
27
+ | `--post-create` | 否 | 执行 postCreate hook(默认开启,`--no-post-create` 跳过)。详见 [post-create-hook.md](./post-create-hook.md) |
28
+
29
+ **互斥约束:**
30
+
31
+ - `--file` 和 `--tasks` **不能同时使用**
32
+ - 非 `-f` 模式必须指定 `-b`
33
+
34
+ **交互式 Claude Code 界面模式:**
35
+
36
+ 当不传 `--tasks` 也不传 `-f` 时,会创建单个 worktree,然后通过 `spawnSync` + `inherit stdio` 在该 worktree 中直接启动 Claude Code CLI 交互式界面,让用户与 Claude Code 直接交互。
37
+
38
+ 启动命令通过配置项 `claudeCodeCommand`(默认值 `claude`)指定,支持自定义命令及参数。
39
+
40
+ #### 任务文件格式
41
+
42
+ 任务文件使用嵌入 HTML 注释标签的自定义格式,不限制文件类型,标签外的任何文本都不会被解析。
43
+
44
+ ```markdown
45
+ 这里可以写任何说明文字,会被忽略
46
+
47
+ <!-- CLAWT-TASKS:START -->
48
+ # branch: feat-login
49
+ 实现用户登录功能
50
+ <!-- CLAWT-TASKS:END -->
51
+
52
+ <!-- CLAWT-TASKS:START -->
53
+ # branch: fix-bug
54
+ 修复内存泄漏问题
55
+ 这是多行任务描述
56
+ 可以写很多行
57
+ <!-- CLAWT-TASKS:END -->
58
+ ```
59
+
60
+ **格式规则:**
61
+
62
+ 1. **任务块界定**:每个任务用 `<!-- CLAWT-TASKS:START -->` 和 `<!-- CLAWT-TASKS:END -->` 包裹
63
+ 2. **分支名声明**:块内必须有一行 `# branch: <分支名>`(冒号前后的空格可灵活)
64
+ 3. **任务描述**:块内除分支名行以外的所有行,合并为任务描述(支持多行)
65
+ 4. **块外内容忽略**:标签外的任何文本都不会被解析
66
+ 5. **必填校验**:每个块必须包含任务描述;分支名默认必填,但使用 `-b` 参数时分支名为可选(会被忽略,用 `-b` 值自动编号)
67
+
68
+ **解析实现:** `src/utils/task-file.ts` 中的 `parseTaskFile()`、`loadTaskFile()` 和 `parseTasksFromOptions()` 函数,类型定义为 `TaskFileEntry`(`src/types/taskFile.ts`)。
69
+
70
+ #### 任务文件模式运行流程
71
+
72
+ 使用 `-f` 时的执行路径(`handleRun` → `handleRunFromFile`):
73
+
74
+ 1. 调用 `loadTaskFile(options.file)` 读取解析文件
75
+ 2. **有 `-b` 参数**:忽略文件中的分支名,用 `-b` 值自动编号创建 worktree(`createWorktrees(branch, count)`)
76
+ 3. **无 `-b` 参数**:使用文件中每个任务的独立分支名,先 `sanitizeBranchName` 清理后调用 `createWorktreesByBranches(branches)`
77
+ 4. **执行 postCreate hook**:调用 `runPostCreateHooks(worktrees, !options.postCreate)`,以 fire-and-forget 模式后台异步并行执行,不阻塞后续流程。详见 [post-create-hook.md](./post-create-hook.md)
78
+ 5. 调用 `executeBatchTasks(worktrees, tasks, concurrency)` 执行
79
+
80
+ #### --tasks 模式运行流程
81
+
82
+ 1. 若传了 `--tasks`,解析得到任务数组 `tasks[]`;若未传,先检测分支是否已存在(已存在则提示使用 `clawt resume -b <branchName>` 恢复会话),然后创建单个 worktree,执行 postCreate hook(fire-and-forget)后启动 Claude Code 交互式界面(`launchInteractiveClaude(worktree)`),流程结束,不进入后续并行执行阶段
83
+ 2. `n = tasks.length`
84
+ 3. 按照 **5.1** 的流程创建 `n` 个 worktree
85
+ 4. **执行 postCreate hook**:调用 `runPostCreateHooks(worktrees, !options.postCreate)`,以 fire-and-forget 模式后台异步并行执行,不阻塞后续流程。详见 [post-create-hook.md](./post-create-hook.md)
86
+ 5. 通过公共函数 `executeBatchTasks`(`src/utils/task-executor.ts`)启动批量任务执行,该函数负责进度面板渲染、SIGINT 中断处理、并发控制和汇总输出。对每个 worktree 并行启动 Claude Code CLI:
87
+ ```bash
88
+ cd ~/.clawt/worktrees/<project>/<branchName>-<i>
89
+ claude -p "<tasks[i]>" --output-format stream-json --verbose --permission-mode bypassPermissions --append-system-prompt "<系统提示>"
90
+ ```
91
+ 其中 `--append-system-prompt` 使用统一的 `APPEND_SYSTEM_PROMPT` 常量(定义在 `src/constants/config.ts`)。
92
+ 使用 `stream-json` 格式可实时获取 Claude Code 的流式事件(工具调用、文本输出、最终结果),用于在进度面板中显示每个任务的实时活动描述和结果预览。流式事件解析由 `src/utils/stream-parser.ts` 负责。
93
+ 6. 进入**事件监听通知**阶段(见 [5.3](#53-任务完成通知机制))
94
+ 7. **中断处理(Ctrl+C / SIGINT)**
95
+ - 监听 `SIGINT` 信号,用户按下 Ctrl+C 时触发
96
+ - 向所有正在运行的 Claude Code 子进程发送 `SIGTERM` 终止信号
97
+ - 等待所有子进程退出后,进入清理流程:
98
+ - 如果 `autoDeleteBranch` 为 `true`:自动清理本次创建的所有 worktree 和对应分支
99
+ - 否则:交互式询问用户是否移除刚刚创建的 worktree 和对应分支
100
+ - 用户选择保留时,提示可使用 `clawt remove` 手动清理
101
+ - 清理完成后以退出码 `1` 退出
102
+
103
+ **注意:** 当 `n = 1` 时(只有一个任务),worktree 目录命名规则同 **5.1**(不加 `-1` 后缀)。
104
+
105
+ #### `--dry-run` 预览模式
106
+
107
+ 传入 `--dry-run` 时不实际创建 worktree 和执行任务,仅输出预览信息供用户确认。预览由 `printDryRunPreview()`(`src/utils/dry-run.ts`)负责渲染。
108
+
109
+ **输出格式:**
110
+
111
+ ```
112
+ ════════════════════════════════════════
113
+ Dry Run 预览
114
+ ════════════════════════════════════════
115
+ 任务数: 3 │ 并发数: 不限制 │ Worktree: ~/.clawt/worktrees/project
116
+ ────────────────────────────────────────
117
+ ✓ [1/3] feat-login
118
+ 路径: ~/.clawt/worktrees/project/feat-login
119
+ 任务: 实现登录功能
120
+
121
+ ⚠ [2/3] feat-signup — 分支 feat-signup 已存在
122
+ 路径: ~/.clawt/worktrees/project/feat-signup
123
+ 任务: 实现注册功能
124
+
125
+ ✓ [3/3] fix-bug
126
+ 路径: ~/.clawt/worktrees/project/fix-bug
127
+ 任务: 修复内存泄漏
128
+
129
+ ════════════════════════════════════════
130
+ ✓ 预览完成,无冲突。移除 --dry-run 即可正式执行。
131
+ ```
132
+
133
+ **格式规则:**
134
+
135
+ 1. **标题区**:双线分隔符包裹标题 `Dry Run 预览`
136
+ 2. **摘要行**:任务数、并发数、Worktree 目录路径合并为一行,用灰色 `│` 分隔;交互式模式(无 `--tasks`)会额外追加模式信息
137
+ 3. **分支列表**:
138
+ - 正常分支:行首绿色 `✓` + 序号 + 青色分支名
139
+ - 冲突分支:行首黄色 `⚠` + 序号 + 黄色分支名 + 灰色 `—` + 黄色警告文本(如 `分支 xxx 已存在`),警告合并在序号行
140
+ 4. **路径/任务行**:2 空格缩进,灰色标签前缀(`路径:` / `任务:`)
141
+ 5. **任务描述截断**:超过 80 字符时末尾加 `...`,多行合并为单行
142
+ 6. **结尾**:双线分隔符后根据冲突情况输出结论——无冲突时绿色 `✓` 提示,有冲突时黄色 `⚠` 警告
143
+
144
+ **实现要点:**
145
+
146
+ - 常量定义在 `src/constants/messages/run.ts`(`DRY_RUN_*` 系列)
147
+ - `DRY_RUN_WORKTREE_DIR` 前缀为 `Worktree:`(简短形式)
148
+ - `truncateTaskDesc()` 负责截断任务描述(最大长度 80 字符,定义在 `src/utils/dry-run.ts`)
149
+
150
+ ---