clawt 1.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.
Files changed (43) hide show
  1. package/.claude/agent-memory/docs-sync-updater/MEMORY.md +48 -0
  2. package/.claude/agents/docs-sync-updater.md +128 -0
  3. package/CLAUDE.md +71 -0
  4. package/README.md +168 -0
  5. package/dist/index.js +923 -0
  6. package/dist/postinstall.js +71 -0
  7. package/docs/spec.md +710 -0
  8. package/package.json +38 -0
  9. package/scripts/postinstall.ts +116 -0
  10. package/src/commands/create.ts +49 -0
  11. package/src/commands/list.ts +45 -0
  12. package/src/commands/merge.ts +142 -0
  13. package/src/commands/remove.ts +127 -0
  14. package/src/commands/run.ts +310 -0
  15. package/src/commands/validate.ts +137 -0
  16. package/src/constants/branch.ts +6 -0
  17. package/src/constants/config.ts +8 -0
  18. package/src/constants/exitCodes.ts +9 -0
  19. package/src/constants/index.ts +6 -0
  20. package/src/constants/messages.ts +61 -0
  21. package/src/constants/paths.ts +14 -0
  22. package/src/constants/terminal.ts +13 -0
  23. package/src/errors/index.ts +20 -0
  24. package/src/index.ts +55 -0
  25. package/src/logger/index.ts +34 -0
  26. package/src/types/claudeCode.ts +14 -0
  27. package/src/types/command.ts +39 -0
  28. package/src/types/config.ts +7 -0
  29. package/src/types/index.ts +5 -0
  30. package/src/types/taskResult.ts +31 -0
  31. package/src/types/worktree.ts +7 -0
  32. package/src/utils/branch.ts +51 -0
  33. package/src/utils/config.ts +35 -0
  34. package/src/utils/formatter.ts +67 -0
  35. package/src/utils/fs.ts +28 -0
  36. package/src/utils/git.ts +243 -0
  37. package/src/utils/index.ts +35 -0
  38. package/src/utils/prompt.ts +18 -0
  39. package/src/utils/shell.ts +53 -0
  40. package/src/utils/validation.ts +48 -0
  41. package/src/utils/worktree.ts +107 -0
  42. package/tsconfig.json +17 -0
  43. package/tsup.config.ts +25 -0
@@ -0,0 +1,107 @@
1
+ import { join } from 'node:path';
2
+ import { existsSync, readdirSync } from 'node:fs';
3
+ import { WORKTREES_DIR } from '../constants/index.js';
4
+ import { logger } from '../logger/index.js';
5
+ import { createWorktree as gitCreateWorktree, getProjectName, gitWorktreeList, removeWorktreeByPath, deleteBranch, gitWorktreePrune } from './git.js';
6
+ import { sanitizeBranchName, generateBranchNames, validateBranchesNotExist } from './branch.js';
7
+ import { ensureDir, removeEmptyDir } from './fs.js';
8
+ import type { WorktreeInfo } from '../types/index.js';
9
+
10
+ /**
11
+ * 获取当前项目的 worktree 存放目录
12
+ * @returns {string} 项目 worktree 目录路径
13
+ */
14
+ export function getProjectWorktreeDir(): string {
15
+ const projectName = getProjectName();
16
+ return join(WORKTREES_DIR, projectName);
17
+ }
18
+
19
+ /**
20
+ * 批量创建 worktree(串行执行)
21
+ * 包含完整的校验流程:分支名清理 → 分支存在性检查 → 创建
22
+ * @param {string} branchName - 基础分支名
23
+ * @param {number} count - 创建数量
24
+ * @returns {WorktreeInfo[]} 创建的 worktree 信息列表
25
+ */
26
+ export function createWorktrees(branchName: string, count: number): WorktreeInfo[] {
27
+ // 1. 分支名清理
28
+ const sanitized = sanitizeBranchName(branchName);
29
+
30
+ // 2. 生成分支名列表
31
+ const branchNames = generateBranchNames(sanitized, count);
32
+
33
+ // 3. 校验所有分支是否都不存在(在创建任何 worktree 之前)
34
+ validateBranchesNotExist(branchNames);
35
+
36
+ // 4. 确保项目 worktree 目录存在
37
+ const projectDir = getProjectWorktreeDir();
38
+ ensureDir(projectDir);
39
+
40
+ // 5. 串行创建 worktree
41
+ const results: WorktreeInfo[] = [];
42
+ for (const name of branchNames) {
43
+ const worktreePath = join(projectDir, name);
44
+ gitCreateWorktree(name, worktreePath);
45
+ results.push({ path: worktreePath, branch: name });
46
+ logger.info(`worktree 创建完成: ${worktreePath} (分支: ${name})`);
47
+ }
48
+
49
+ return results;
50
+ }
51
+
52
+ /**
53
+ * 获取当前项目在 ~/.clawt/worktrees/<project>/ 下的所有 worktree
54
+ * 通过与 git worktree list 交叉验证确认有效性
55
+ * @returns {WorktreeInfo[]} 有效的 worktree 列表
56
+ */
57
+ export function getProjectWorktrees(): WorktreeInfo[] {
58
+ const projectDir = getProjectWorktreeDir();
59
+
60
+ if (!existsSync(projectDir)) {
61
+ return [];
62
+ }
63
+
64
+ // 获取 git worktree list 的输出,用于交叉验证
65
+ const worktreeListOutput = gitWorktreeList();
66
+ const registeredPaths = new Set(
67
+ worktreeListOutput.split('\n').map((line) => line.split(/\s+/)[0]),
68
+ );
69
+
70
+ const entries = readdirSync(projectDir, { withFileTypes: true });
71
+ const worktrees: WorktreeInfo[] = [];
72
+
73
+ for (const entry of entries) {
74
+ if (!entry.isDirectory()) {
75
+ continue;
76
+ }
77
+ const fullPath = join(projectDir, entry.name);
78
+ // 交叉验证:路径必须在 git worktree list 中
79
+ if (registeredPaths.has(fullPath)) {
80
+ worktrees.push({
81
+ path: fullPath,
82
+ branch: entry.name,
83
+ });
84
+ }
85
+ }
86
+
87
+ return worktrees;
88
+ }
89
+
90
+ /**
91
+ * 批量清理 worktree 及对应分支
92
+ * @param {WorktreeInfo[]} worktrees - 待清理的 worktree 列表
93
+ */
94
+ export function cleanupWorktrees(worktrees: WorktreeInfo[]): void {
95
+ for (const wt of worktrees) {
96
+ try {
97
+ removeWorktreeByPath(wt.path);
98
+ deleteBranch(wt.branch);
99
+ logger.info(`已清理 worktree 和分支: ${wt.branch}`);
100
+ } catch (error) {
101
+ logger.error(`清理 worktree 失败: ${wt.path} - ${error}`);
102
+ }
103
+ }
104
+ gitWorktreePrune();
105
+ const projectDir = getProjectWorktreeDir();
106
+ removeEmptyDir(projectDir);
107
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "esModuleInterop": true,
7
+ "strict": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": ".",
11
+ "declaration": true,
12
+ "resolveJsonModule": true,
13
+ "forceConsistentCasingInFileNames": true
14
+ },
15
+ "include": ["src/**/*", "scripts/**/*"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig([
4
+ {
5
+ entry: ['src/index.ts'],
6
+ format: ['esm'],
7
+ target: 'node18',
8
+ outDir: 'dist',
9
+ clean: true,
10
+ banner: {
11
+ js: [
12
+ '#!/usr/bin/env node',
13
+ 'import { createRequire as __clawt_createRequire } from "module";',
14
+ 'const require = __clawt_createRequire(import.meta.url);',
15
+ ].join('\n'),
16
+ },
17
+ },
18
+ {
19
+ entry: ['scripts/postinstall.ts'],
20
+ format: ['esm'],
21
+ target: 'node18',
22
+ outDir: 'dist',
23
+ clean: false,
24
+ },
25
+ ]);