clawt 3.2.0 → 3.3.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 CHANGED
@@ -203,6 +203,14 @@ clawt status -i # 交互式面板模式(实时刷新,支持键盘导
203
203
  clawt reset
204
204
  ```
205
205
 
206
+ ### `clawt home` — 切换回主工作分支
207
+
208
+ ```bash
209
+ clawt home
210
+ ```
211
+
212
+ 如果当前已在主工作分支上,会提示无需切换。
213
+
206
214
  ### `clawt projects` — 跨项目 worktree 概览
207
215
 
208
216
  ```bash
package/dist/index.js CHANGED
@@ -299,7 +299,11 @@ ${failures.map((f) => ` \u2717 ${f.path}: ${f.error}`).join("\n")}`,
299
299
  /** 用户选择保留本地分支 */
300
300
  REMOVE_BRANCHES_KEPT: "\u5DF2\u4FDD\u7559\u672C\u5730\u5206\u652F\uFF0C\u53EF\u7A0D\u540E\u4F7F\u7528 git branch -D <\u5206\u652F\u540D> \u624B\u52A8\u5220\u9664",
301
301
  /** 确认删除本地分支和验证分支 */
302
- REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F"
302
+ REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F",
303
+ /** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
304
+ REMOVE_BRANCH_IS_CURRENT: (branch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`,
305
+ /** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
306
+ REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch, validateBranch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u7684\u9A8C\u8BC1\u5206\u652F ${validateBranch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`
303
307
  };
304
308
 
305
309
  // src/constants/messages/reset.ts
@@ -469,6 +473,14 @@ var INIT_MESSAGES = {
469
473
  INIT_SET_SUCCESS: (key, value) => `\u2713 \u9879\u76EE\u914D\u7F6E ${key} \u5DF2\u8BBE\u7F6E\u4E3A ${value}`
470
474
  };
471
475
 
476
+ // src/constants/messages/home.ts
477
+ var HOME_MESSAGES = {
478
+ /** 已在主工作分支上 */
479
+ HOME_ALREADY_ON_MAIN: (branch) => `\u5DF2\u5728\u4E3B\u5DE5\u4F5C\u5206\u652F ${branch} \u4E0A\uFF0C\u65E0\u9700\u5207\u6362`,
480
+ /** 切换成功 */
481
+ HOME_SWITCH_SUCCESS: (from, to) => `\u2713 \u5DF2\u4ECE ${from} \u5207\u6362\u5230\u4E3B\u5DE5\u4F5C\u5206\u652F ${to}`
482
+ };
483
+
472
484
  // src/constants/messages/interactive-panel.ts
473
485
  import chalk from "chalk";
474
486
 
@@ -541,7 +553,8 @@ var MESSAGES = {
541
553
  ...ALIAS_MESSAGES,
542
554
  ...PROJECTS_MESSAGES,
543
555
  ...COMPLETION_MESSAGES,
544
- ...INIT_MESSAGES
556
+ ...INIT_MESSAGES,
557
+ ...HOME_MESSAGES
545
558
  };
546
559
 
547
560
  // src/constants/exitCodes.ts
@@ -3811,6 +3824,16 @@ async function handleRemove(options) {
3811
3824
  printInfo(MESSAGES.NO_WORKTREES);
3812
3825
  return;
3813
3826
  }
3827
+ const currentBranch = getCurrentBranch();
3828
+ for (const wt of worktreesToRemove) {
3829
+ if (wt.branch === currentBranch) {
3830
+ throw new ClawtError(MESSAGES.REMOVE_BRANCH_IS_CURRENT(wt.branch));
3831
+ }
3832
+ const validateBranch = getValidateBranchName(wt.branch);
3833
+ if (validateBranch === currentBranch) {
3834
+ throw new ClawtError(MESSAGES.REMOVE_VALIDATE_BRANCH_IS_CURRENT(wt.branch, validateBranch));
3835
+ }
3836
+ }
3814
3837
  printInfo("\u5373\u5C06\u79FB\u9664\u4EE5\u4E0B worktree \u53CA\u672C\u5730\u5206\u652F\uFF1A\n");
3815
3838
  worktreesToRemove.forEach((wt, index) => {
3816
3839
  printInfo(` ${index + 1}. ${wt.path} \u2192 \u5206\u652F: ${wt.branch} \u9A8C\u8BC1\u5206\u652F: ${getValidateBranchName(wt.branch)}`);
@@ -5144,6 +5167,25 @@ async function handleInit(options) {
5144
5167
  }
5145
5168
  }
5146
5169
 
5170
+ // src/commands/home.ts
5171
+ function registerHomeCommand(program2) {
5172
+ program2.command("home").description("\u5207\u6362\u56DE\u4E3B\u5DE5\u4F5C\u5206\u652F").action(async () => {
5173
+ await handleHome();
5174
+ });
5175
+ }
5176
+ async function handleHome() {
5177
+ validateMainWorktree();
5178
+ requireProjectConfig();
5179
+ const mainBranch = getMainWorkBranch();
5180
+ const currentBranch = getCurrentBranch();
5181
+ if (currentBranch === mainBranch) {
5182
+ printInfo(MESSAGES.HOME_ALREADY_ON_MAIN(mainBranch));
5183
+ return;
5184
+ }
5185
+ await ensureOnMainWorkBranch();
5186
+ printSuccess(MESSAGES.HOME_SWITCH_SUCCESS(currentBranch, mainBranch));
5187
+ }
5188
+
5147
5189
  // src/index.ts
5148
5190
  var require2 = createRequire(import.meta.url);
5149
5191
  var { version } = require2("../package.json");
@@ -5170,6 +5212,7 @@ registerAliasCommand(program);
5170
5212
  registerProjectsCommand(program);
5171
5213
  registerCompletionCommand(program);
5172
5214
  registerInitCommand(program);
5215
+ registerHomeCommand(program);
5173
5216
  var config = loadConfig();
5174
5217
  applyAliases(program, config.aliases);
5175
5218
  process.on("uncaughtException", (error) => {
@@ -290,7 +290,11 @@ ${failures.map((f) => ` \u2717 ${f.path}: ${f.error}`).join("\n")}`,
290
290
  /** 用户选择保留本地分支 */
291
291
  REMOVE_BRANCHES_KEPT: "\u5DF2\u4FDD\u7559\u672C\u5730\u5206\u652F\uFF0C\u53EF\u7A0D\u540E\u4F7F\u7528 git branch -D <\u5206\u652F\u540D> \u624B\u52A8\u5220\u9664",
292
292
  /** 确认删除本地分支和验证分支 */
293
- REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F"
293
+ REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F",
294
+ /** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
295
+ REMOVE_BRANCH_IS_CURRENT: (branch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`,
296
+ /** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
297
+ REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch, validateBranch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u7684\u9A8C\u8BC1\u5206\u652F ${validateBranch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`
294
298
  };
295
299
 
296
300
  // src/constants/messages/reset.ts
@@ -446,6 +450,14 @@ var INIT_MESSAGES = {
446
450
  INIT_SET_SUCCESS: (key, value) => `\u2713 \u9879\u76EE\u914D\u7F6E ${key} \u5DF2\u8BBE\u7F6E\u4E3A ${value}`
447
451
  };
448
452
 
453
+ // src/constants/messages/home.ts
454
+ var HOME_MESSAGES = {
455
+ /** 已在主工作分支上 */
456
+ HOME_ALREADY_ON_MAIN: (branch) => `\u5DF2\u5728\u4E3B\u5DE5\u4F5C\u5206\u652F ${branch} \u4E0A\uFF0C\u65E0\u9700\u5207\u6362`,
457
+ /** 切换成功 */
458
+ HOME_SWITCH_SUCCESS: (from, to) => `\u2713 \u5DF2\u4ECE ${from} \u5207\u6362\u5230\u4E3B\u5DE5\u4F5C\u5206\u652F ${to}`
459
+ };
460
+
449
461
  // src/constants/messages/interactive-panel.ts
450
462
  import chalk from "chalk";
451
463
 
@@ -498,7 +510,8 @@ var MESSAGES = {
498
510
  ...ALIAS_MESSAGES,
499
511
  ...PROJECTS_MESSAGES,
500
512
  ...COMPLETION_MESSAGES,
501
- ...INIT_MESSAGES
513
+ ...INIT_MESSAGES,
514
+ ...HOME_MESSAGES
502
515
  };
503
516
 
504
517
  // src/constants/terminal.ts
package/docs/home.md ADDED
@@ -0,0 +1,54 @@
1
+ ### 5.20 切换回主工作分支
2
+
3
+ **命令:**
4
+
5
+ ```bash
6
+ clawt home
7
+ ```
8
+
9
+ **参数:**
10
+
11
+ 无参数。
12
+
13
+ **功能说明:**
14
+
15
+ 快速切换回项目的主工作分支。当用户在主 worktree 中处于验证分支或其他分支时,可通过 `clawt home` 一键切换回 `clawtMainWorkBranch` 所记录的主工作分支。
16
+
17
+ **运行流程:**
18
+
19
+ 1. **主 worktree 校验** (2.1)
20
+ 2. **项目级配置校验**:调用 `requireProjectConfig()` 检查项目是否已初始化
21
+ 3. **获取分支信息**:
22
+ - 通过 `getMainWorkBranch()` 获取主工作分支名
23
+ - 通过 `getCurrentBranch()` 获取当前所在分支名
24
+ 4. **判断是否需要切换**:
25
+ - 当前分支 === 主工作分支 → 输出提示信息,无需切换
26
+ - 当前分支 !== 主工作分支 → 调用 `ensureOnMainWorkBranch()` 执行切换
27
+ 5. **输出结果**
28
+
29
+ **输出格式:**
30
+
31
+ ```
32
+ # 已在主工作分支上
33
+ ℹ 已在主工作分支 main 上,无需切换
34
+
35
+ # 切换成功
36
+ ✓ 已从 clawt-validate-feat-login 切换到主工作分支 main
37
+ ```
38
+
39
+ **消息常量:**
40
+
41
+ 定义在 `src/constants/messages/home.ts`:
42
+
43
+ | 常量 | 说明 |
44
+ | --- | --- |
45
+ | `HOME_ALREADY_ON_MAIN(branch)` | 已在主工作分支上,无需切换 |
46
+ | `HOME_SWITCH_SUCCESS(from, to)` | 切换成功提示,显示原分支和目标分支 |
47
+
48
+ **实现要点:**
49
+
50
+ - 命令注册函数 `registerHomeCommand` 位于 `src/commands/home.ts`
51
+ - 依赖 `validateMainWorktree`、`requireProjectConfig`、`ensureOnMainWorkBranch`、`getCurrentBranch`、`getMainWorkBranch` 等工具函数
52
+ - `requireProjectConfig()` 为显式调用,因为 home 命令不经过 `ensureOnMainWorkBranch()` 的隐式校验路径(仅在需要切换时才调用 `ensureOnMainWorkBranch()`)
53
+
54
+ ---
package/docs/spec.md CHANGED
@@ -34,6 +34,7 @@
34
34
  - [5.17 自动更新检查](./update-check.md)
35
35
  - [5.18 跨项目 Worktree 概览](./projects.md)
36
36
  - [5.19 初始化项目级配置](./init.md)
37
+ - [5.20 切换回主工作分支](./home.md)
37
38
  - [6. 验证架构规则](#6-验证架构规则)
38
39
  - [7. 错误处理规范](#7-错误处理规范)
39
40
  - [8. 非功能性需求](#8-非功能性需求)
@@ -292,6 +293,7 @@ async function interactiveConfigEditor<T extends object>(
292
293
  | `clawt alias` | 管理命令别名(列出 / 设置 / 移除) | 5.15 |
293
294
  | `clawt completion` | 为终端提供 shell 自动补全功能(bash/zsh) | 5.16 |
294
295
  | `clawt projects` | 展示所有项目的 worktree 概览,或查看指定项目的 worktree 详情 | 5.17 |
296
+ | `clawt home` | 快速切换回主工作分支 | 5.20 |
295
297
 
296
298
  **全局选项:**
297
299
 
@@ -325,6 +327,7 @@ async function interactiveConfigEditor<T extends object>(
325
327
  - [5.17 自动更新检查](./update-check.md)
326
328
  - [5.18 跨项目 Worktree 概览](./projects.md)
327
329
  - [5.19 初始化项目级配置](./init.md)
330
+ - [5.20 切换回主工作分支](./home.md)
328
331
 
329
332
  ---
330
333
 
@@ -333,12 +336,12 @@ async function interactiveConfigEditor<T extends object>(
333
336
  以下规则适用于验证分支架构的所有实现工作:
334
337
 
335
338
  1. **不兼容旧版本**:本次重构不考虑旧版本数据、旧版本创建的 worktree 或旧版本配置的兼容性。所有命令均假定验证分支和项目级配置已按新架构存在。用户需删除旧 worktree 后重新创建。
336
- 2. **项目级配置前置校验**:仅对 create、run、validate、sync、remove、merge、reset 这 7 个核心命令添加检测,执行时必须先检查项目级配置(`~/.clawt/projects/<projectName>/config.json`)是否存在且包含 `clawtMainWorkBranch`。如果不存在,直接报错退出并提示用户先执行 `clawt init`:
339
+ 2. **项目级配置前置校验**:仅对 create、run、validate、sync、remove、merge、reset、home8 个核心命令添加检测,执行时必须先检查项目级配置(`~/.clawt/projects/<projectName>/config.json`)是否存在且包含 `clawtMainWorkBranch`。如果不存在,直接报错退出并提示用户先执行 `clawt init`:
337
340
  ```
338
341
  ✗ 该项目尚未初始化,请先执行 clawt init -b<branchName>设置主工作分支
339
342
  ```
340
343
  其他命令(list、resume、config、status、alias、projects、completion)不受影响,无需添加该校验。
341
- > **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、validate、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。sync 和 remove 命令因不依赖主 worktree 的分支状态而不调用 `ensureOnMainWorkBranch`,需自行显式调用 `requireProjectConfig()`。reset 命令同理,也需自行调用 `requireProjectConfig()`。
344
+ > **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、validate、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。sync 和 remove 命令因不依赖主 worktree 的分支状态而不调用 `ensureOnMainWorkBranch`,需自行显式调用 `requireProjectConfig()`。reset 和 home 命令同理,也需自行调用 `requireProjectConfig()`。
342
345
  3. **主分支名统一从项目级配置获取**:所有需要获取主分支名的场景(sync 中合并主分支、merge 中计算 merge-base、切回主分支等),统一使用项目级配置中的 `clawtMainWorkBranch`,不再通过 `getCurrentBranch(mainWorktreePath)` 动态获取。因为在新架构下,主 worktree 可能处于验证分支上,`getCurrentBranch` 会返回验证分支名而非真正的主工作分支名。
343
346
  4. **测试文件全量更新**:本次重构涉及的所有命令(init、create、run、validate、sync、remove、merge、reset),其对应的测试文件必须同步更新,确保覆盖新增的验证分支逻辑、项目级配置逻辑和变更后的流程。
344
347
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawt",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "本地并行执行多个Claude Code Agent任务,融合 Git Worktree 与 Claude Code CLI 的命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,43 @@
1
+ import type { Command } from 'commander';
2
+ import { MESSAGES } from '../constants/index.js';
3
+ import {
4
+ validateMainWorktree,
5
+ requireProjectConfig,
6
+ ensureOnMainWorkBranch,
7
+ getCurrentBranch,
8
+ getMainWorkBranch,
9
+ printSuccess,
10
+ printInfo,
11
+ } from '../utils/index.js';
12
+
13
+ /**
14
+ * 注册 home 命令:快速切换回主工作分支
15
+ * @param {Command} program - Commander 实例
16
+ */
17
+ export function registerHomeCommand(program: Command): void {
18
+ program
19
+ .command('home')
20
+ .description('切换回主工作分支')
21
+ .action(async () => {
22
+ await handleHome();
23
+ });
24
+ }
25
+
26
+ /**
27
+ * 执行 home 命令:切换回主工作分支
28
+ */
29
+ async function handleHome(): Promise<void> {
30
+ validateMainWorktree();
31
+ requireProjectConfig();
32
+
33
+ const mainBranch = getMainWorkBranch();
34
+ const currentBranch = getCurrentBranch();
35
+
36
+ if (currentBranch === mainBranch) {
37
+ printInfo(MESSAGES.HOME_ALREADY_ON_MAIN(mainBranch));
38
+ return;
39
+ }
40
+
41
+ await ensureOnMainWorkBranch();
42
+ printSuccess(MESSAGES.HOME_SWITCH_SUCCESS(currentBranch, mainBranch));
43
+ }
@@ -24,6 +24,7 @@ import {
24
24
  getValidateBranchName,
25
25
  deleteValidateBranch,
26
26
  requireProjectConfig,
27
+ getCurrentBranch,
27
28
  } from '../utils/index.js';
28
29
  import type { WorktreeMultiResolveMessages } from '../utils/index.js';
29
30
 
@@ -77,6 +78,18 @@ async function handleRemove(options: RemoveOptions): Promise<void> {
77
78
  return;
78
79
  }
79
80
 
81
+ // 检查待移除的分支是否是主 worktree 当前所在分支
82
+ const currentBranch = getCurrentBranch();
83
+ for (const wt of worktreesToRemove) {
84
+ if (wt.branch === currentBranch) {
85
+ throw new ClawtError(MESSAGES.REMOVE_BRANCH_IS_CURRENT(wt.branch));
86
+ }
87
+ const validateBranch = getValidateBranchName(wt.branch);
88
+ if (validateBranch === currentBranch) {
89
+ throw new ClawtError(MESSAGES.REMOVE_VALIDATE_BRANCH_IS_CURRENT(wt.branch, validateBranch));
90
+ }
91
+ }
92
+
80
93
  // 列出即将移除的 worktree
81
94
  printInfo('即将移除以下 worktree 及本地分支:\n');
82
95
  worktreesToRemove.forEach((wt, index) => {
@@ -0,0 +1,7 @@
1
+ /** home 命令专属提示消息 */
2
+ export const HOME_MESSAGES = {
3
+ /** 已在主工作分支上 */
4
+ HOME_ALREADY_ON_MAIN: (branch: string) => `已在主工作分支 ${branch} 上,无需切换`,
5
+ /** 切换成功 */
6
+ HOME_SWITCH_SUCCESS: (from: string, to: string) => `✓ 已从 ${from} 切换到主工作分支 ${to}`,
7
+ } as const;
@@ -14,6 +14,7 @@ import { PROJECTS_MESSAGES } from './projects.js';
14
14
  import { COMPLETION_MESSAGES } from './completion.js';
15
15
  import { UPDATE_MESSAGES, UPDATE_COMMANDS } from './update.js';
16
16
  import { INIT_MESSAGES } from './init.js';
17
+ import { HOME_MESSAGES } from './home.js';
17
18
  import { PANEL_FOOTER_SHORTCUTS, PANEL_FOOTER_COUNTDOWN, PANEL_OVERFLOW_DOWN_HINT, PANEL_OVERFLOW_UP_HINT, PANEL_SNAPSHOT_SUMMARY, PANEL_NO_WORKTREES as PANEL_NO_WORKTREES_MSG, PANEL_PRESS_ENTER_TO_RETURN, PANEL_NOT_TTY, PANEL_TITLE } from './interactive-panel.js';
18
19
 
19
20
  export { CONFIG_ALIAS_DISABLED_HINT };
@@ -40,4 +41,5 @@ export const MESSAGES = {
40
41
  ...PROJECTS_MESSAGES,
41
42
  ...COMPLETION_MESSAGES,
42
43
  ...INIT_MESSAGES,
44
+ ...HOME_MESSAGES,
43
45
  } as const;
@@ -16,4 +16,10 @@ export const REMOVE_MESSAGES = {
16
16
  REMOVE_BRANCHES_KEPT: '已保留本地分支,可稍后使用 git branch -D <分支名> 手动删除',
17
17
  /** 确认删除本地分支和验证分支 */
18
18
  REMOVE_CONFIRM_DELETE_BRANCHES: '是否同时删除对应的本地分支和验证分支?',
19
+ /** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
20
+ REMOVE_BRANCH_IS_CURRENT: (branch: string) =>
21
+ `无法移除:分支 ${branch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
22
+ /** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
23
+ REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch: string, validateBranch: string) =>
24
+ `无法移除:分支 ${branch} 的验证分支 ${validateBranch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
19
25
  } as const;
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ import { registerAliasCommand } from './commands/alias.js';
19
19
  import { registerProjectsCommand } from './commands/projects.js';
20
20
  import { registerCompletionCommand } from './commands/completion.js';
21
21
  import { registerInitCommand } from './commands/init.js';
22
+ import { registerHomeCommand } from './commands/home.js';
22
23
 
23
24
  // 从 package.json 读取版本号,避免硬编码
24
25
  const require = createRequire(import.meta.url);
@@ -58,6 +59,7 @@ registerAliasCommand(program);
58
59
  registerProjectsCommand(program);
59
60
  registerCompletionCommand(program);
60
61
  registerInitCommand(program);
62
+ registerHomeCommand(program);
61
63
 
62
64
  // 加载配置并应用命令别名
63
65
  const config = loadConfig();
@@ -25,6 +25,10 @@ vi.mock('../../../src/constants/index.js', () => ({
25
25
  REMOVE_MULTIPLE_MATCHES: (name: string) => `"${name}" 匹配到多个分支`,
26
26
  REMOVE_NO_MATCH: (name: string, branches: string[]) => `未找到与 "${name}" 匹配的分支,可用:${branches.join(', ')}`,
27
27
  REMOVE_BRANCHES_KEPT: '已保留本地分支,可稍后使用 git branch -D <分支名> 手动删除',
28
+ REMOVE_BRANCH_IS_CURRENT: (branch: string) =>
29
+ `无法移除:分支 ${branch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
30
+ REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch: string, validateBranch: string) =>
31
+ `无法移除:分支 ${branch} 的验证分支 ${validateBranch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
28
32
  },
29
33
  }));
30
34
 
@@ -49,6 +53,7 @@ vi.mock('../../../src/utils/index.js', () => ({
49
53
  requireProjectConfig: vi.fn().mockReturnValue({ clawtMainWorkBranch: 'main' }),
50
54
  getValidateBranchName: vi.fn((name: string) => `clawt-validate-${name}`),
51
55
  deleteValidateBranch: vi.fn(),
56
+ getCurrentBranch: vi.fn(),
52
57
  }));
53
58
 
54
59
  import { registerRemoveCommand } from '../../../src/commands/remove.js';
@@ -66,6 +71,7 @@ import {
66
71
  printError,
67
72
  printHint,
68
73
  resolveTargetWorktrees,
74
+ getCurrentBranch,
69
75
  } from '../../../src/utils/index.js';
70
76
 
71
77
  const mockedGetProjectName = vi.mocked(getProjectName);
@@ -80,6 +86,7 @@ const mockedPrintSuccess = vi.mocked(printSuccess);
80
86
  const mockedPrintError = vi.mocked(printError);
81
87
  const mockedPrintHint = vi.mocked(printHint);
82
88
  const mockedResolveTargetWorktrees = vi.mocked(resolveTargetWorktrees);
89
+ const mockedGetCurrentBranch = vi.mocked(getCurrentBranch);
83
90
 
84
91
  beforeEach(() => {
85
92
  vi.mocked(validateMainWorktree).mockReset();
@@ -95,6 +102,8 @@ beforeEach(() => {
95
102
  mockedPrintError.mockReset();
96
103
  mockedPrintHint.mockReset();
97
104
  mockedResolveTargetWorktrees.mockReset();
105
+ mockedGetCurrentBranch.mockReset();
106
+ mockedGetCurrentBranch.mockReturnValue('main');
98
107
  });
99
108
 
100
109
  describe('registerRemoveCommand', () => {