clawt 1.0.4 → 1.0.5

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/dist/index.js CHANGED
@@ -72,10 +72,14 @@ var MESSAGES = {
72
72
  INTERRUPT_CLEANED: (count) => `\u2713 \u5DF2\u6E05\u7406 ${count} \u4E2A worktree \u548C\u5BF9\u5E94\u5206\u652F`,
73
73
  /** 中断后保留 worktree */
74
74
  INTERRUPT_KEPT: "\u5DF2\u4FDD\u7559 worktree\uFF0C\u53EF\u7A0D\u540E\u4F7F\u7528 clawt remove \u624B\u52A8\u6E05\u7406",
75
+ /** 配置文件损坏,已重新生成默认配置 */
76
+ CONFIG_CORRUPTED: "\u914D\u7F6E\u6587\u4EF6\u635F\u574F\u6216\u65E0\u6CD5\u89E3\u6790\uFF0C\u5DF2\u91CD\u65B0\u751F\u6210\u9ED8\u8BA4\u914D\u7F6E",
75
77
  /** 分隔线 */
76
78
  SEPARATOR: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
77
79
  /** 粗分隔线 */
78
- DOUBLE_SEPARATOR: "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"
80
+ DOUBLE_SEPARATOR: "\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
81
+ /** 创建数量参数无效 */
82
+ INVALID_COUNT: (value) => `\u65E0\u6548\u7684\u521B\u5EFA\u6570\u91CF: "${value}"\uFF0C\u8BF7\u8F93\u5165\u6B63\u6574\u6570`
79
83
  };
80
84
 
81
85
  // src/constants/exitCodes.ts
@@ -426,13 +430,22 @@ function cleanupWorktrees(worktrees) {
426
430
  }
427
431
 
428
432
  // src/utils/config.ts
429
- import { existsSync as existsSync4, readFileSync } from "fs";
433
+ import { existsSync as existsSync4, readFileSync, writeFileSync } from "fs";
430
434
  function loadConfig() {
431
435
  if (!existsSync4(CONFIG_PATH)) {
432
436
  return { ...DEFAULT_CONFIG };
433
437
  }
434
- const raw = readFileSync(CONFIG_PATH, "utf-8");
435
- return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
438
+ try {
439
+ const raw = readFileSync(CONFIG_PATH, "utf-8");
440
+ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
441
+ } catch {
442
+ logger.warn(MESSAGES.CONFIG_CORRUPTED);
443
+ writeDefaultConfig();
444
+ return { ...DEFAULT_CONFIG };
445
+ }
446
+ }
447
+ function writeDefaultConfig() {
448
+ writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2), "utf-8");
436
449
  }
437
450
  function getConfigValue(key) {
438
451
  const config = loadConfig();
@@ -480,6 +493,12 @@ function registerCreateCommand(program2) {
480
493
  function handleCreate(options) {
481
494
  validateMainWorktree();
482
495
  const count = Number(options.number);
496
+ if (!Number.isInteger(count) || count <= 0) {
497
+ throw new ClawtError(
498
+ MESSAGES.INVALID_COUNT(options.number),
499
+ EXIT_CODES.ARGUMENT_ERROR
500
+ );
501
+ }
483
502
  logger.info(`create \u547D\u4EE4\u6267\u884C\uFF0C\u5206\u652F: ${options.branch}\uFF0C\u6570\u91CF: ${count}`);
484
503
  const worktrees = createWorktrees(options.branch, count);
485
504
  printSuccess(MESSAGES.WORKTREE_CREATED(worktrees.length));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawt",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "本地并行执行多个Claude Code Agent任务,融合 Git Worktree 与 Claude Code CLI 的命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,5 +1,6 @@
1
1
  import type { Command } from 'commander';
2
- import { MESSAGES } from '../constants/index.js';
2
+ import { MESSAGES, EXIT_CODES } from '../constants/index.js';
3
+ import { ClawtError } from '../errors/index.js';
3
4
  import { logger } from '../logger/index.js';
4
5
  import type { CreateOptions } from '../types/index.js';
5
6
  import {
@@ -33,6 +34,15 @@ function handleCreate(options: CreateOptions): void {
33
34
  validateMainWorktree();
34
35
 
35
36
  const count = Number(options.number);
37
+
38
+ // 校验创建数量必须为正整数
39
+ if (!Number.isInteger(count) || count <= 0) {
40
+ throw new ClawtError(
41
+ MESSAGES.INVALID_COUNT(options.number),
42
+ EXIT_CODES.ARGUMENT_ERROR,
43
+ );
44
+ }
45
+
36
46
  logger.info(`create 命令执行,分支: ${options.branch},数量: ${count}`);
37
47
 
38
48
  const worktrees = createWorktrees(options.branch, count);
@@ -54,8 +54,12 @@ export const MESSAGES = {
54
54
  INTERRUPT_CLEANED: (count: number) => `✓ 已清理 ${count} 个 worktree 和对应分支`,
55
55
  /** 中断后保留 worktree */
56
56
  INTERRUPT_KEPT: '已保留 worktree,可稍后使用 clawt remove 手动清理',
57
+ /** 配置文件损坏,已重新生成默认配置 */
58
+ CONFIG_CORRUPTED: '配置文件损坏或无法解析,已重新生成默认配置',
57
59
  /** 分隔线 */
58
60
  SEPARATOR: '────────────────────────────────────────',
59
61
  /** 粗分隔线 */
60
62
  DOUBLE_SEPARATOR: '════════════════════════════════════════',
63
+ /** 创建数量参数无效 */
64
+ INVALID_COUNT: (value: string) => `无效的创建数量: "${value}",请输入正整数`,
61
65
  } as const;
@@ -2,8 +2,8 @@
2
2
  export interface CreateOptions {
3
3
  /** 分支名 */
4
4
  branch: string;
5
- /** 创建数量,默认 1 */
6
- number: number;
5
+ /** 创建数量(Commander 传入为字符串),默认 '1' */
6
+ number: string;
7
7
  }
8
8
 
9
9
  /** run 命令选项 */
@@ -1,18 +1,34 @@
1
1
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { CONFIG_PATH, CLAWT_HOME, LOGS_DIR, WORKTREES_DIR, DEFAULT_CONFIG } from '../constants/index.js';
2
+ import { CONFIG_PATH, CLAWT_HOME, LOGS_DIR, WORKTREES_DIR, DEFAULT_CONFIG, MESSAGES } from '../constants/index.js';
3
3
  import { ensureDir } from './fs.js';
4
+ import { logger } from '../logger/index.js';
4
5
  import type { ClawtConfig } from '../types/index.js';
5
6
 
6
7
  /**
7
8
  * 加载全局配置,不存在则返回默认配置
9
+ * 配置文件损坏或无法解析时,视为不存在,重新生成默认配置
8
10
  * @returns {ClawtConfig} 配置对象
9
11
  */
10
12
  export function loadConfig(): ClawtConfig {
11
13
  if (!existsSync(CONFIG_PATH)) {
12
14
  return { ...DEFAULT_CONFIG };
13
15
  }
14
- const raw = readFileSync(CONFIG_PATH, 'utf-8');
15
- return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
16
+ try {
17
+ const raw = readFileSync(CONFIG_PATH, 'utf-8');
18
+ return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
19
+ } catch {
20
+ // 配置文件损坏或无法解析时,重新生成默认配置
21
+ logger.warn(MESSAGES.CONFIG_CORRUPTED);
22
+ writeDefaultConfig();
23
+ return { ...DEFAULT_CONFIG };
24
+ }
25
+ }
26
+
27
+ /**
28
+ * 将默认配置写入配置文件
29
+ */
30
+ function writeDefaultConfig(): void {
31
+ writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2), 'utf-8');
16
32
  }
17
33
 
18
34
  /**