cluttry 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 (79) hide show
  1. package/.vwt.json +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +444 -0
  4. package/dist/commands/doctor.d.ts +7 -0
  5. package/dist/commands/doctor.d.ts.map +1 -0
  6. package/dist/commands/doctor.js +198 -0
  7. package/dist/commands/doctor.js.map +1 -0
  8. package/dist/commands/init.d.ts +11 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +90 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/list.d.ts +11 -0
  13. package/dist/commands/list.d.ts.map +1 -0
  14. package/dist/commands/list.js +106 -0
  15. package/dist/commands/list.js.map +1 -0
  16. package/dist/commands/open.d.ts +11 -0
  17. package/dist/commands/open.d.ts.map +1 -0
  18. package/dist/commands/open.js +52 -0
  19. package/dist/commands/open.js.map +1 -0
  20. package/dist/commands/prune.d.ts +7 -0
  21. package/dist/commands/prune.d.ts.map +1 -0
  22. package/dist/commands/prune.js +33 -0
  23. package/dist/commands/prune.js.map +1 -0
  24. package/dist/commands/rm.d.ts +13 -0
  25. package/dist/commands/rm.d.ts.map +1 -0
  26. package/dist/commands/rm.js +99 -0
  27. package/dist/commands/rm.js.map +1 -0
  28. package/dist/commands/spawn.d.ts +17 -0
  29. package/dist/commands/spawn.d.ts.map +1 -0
  30. package/dist/commands/spawn.js +127 -0
  31. package/dist/commands/spawn.js.map +1 -0
  32. package/dist/index.d.ts +8 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +101 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/lib/config.d.ts +44 -0
  37. package/dist/lib/config.d.ts.map +1 -0
  38. package/dist/lib/config.js +109 -0
  39. package/dist/lib/config.js.map +1 -0
  40. package/dist/lib/git.d.ts +73 -0
  41. package/dist/lib/git.d.ts.map +1 -0
  42. package/dist/lib/git.js +225 -0
  43. package/dist/lib/git.js.map +1 -0
  44. package/dist/lib/output.d.ts +33 -0
  45. package/dist/lib/output.d.ts.map +1 -0
  46. package/dist/lib/output.js +83 -0
  47. package/dist/lib/output.js.map +1 -0
  48. package/dist/lib/paths.d.ts +36 -0
  49. package/dist/lib/paths.d.ts.map +1 -0
  50. package/dist/lib/paths.js +84 -0
  51. package/dist/lib/paths.js.map +1 -0
  52. package/dist/lib/secrets.d.ts +50 -0
  53. package/dist/lib/secrets.d.ts.map +1 -0
  54. package/dist/lib/secrets.js +146 -0
  55. package/dist/lib/secrets.js.map +1 -0
  56. package/dist/lib/types.d.ts +63 -0
  57. package/dist/lib/types.d.ts.map +1 -0
  58. package/dist/lib/types.js +5 -0
  59. package/dist/lib/types.js.map +1 -0
  60. package/package.json +41 -0
  61. package/src/commands/doctor.ts +222 -0
  62. package/src/commands/init.ts +120 -0
  63. package/src/commands/list.ts +133 -0
  64. package/src/commands/open.ts +70 -0
  65. package/src/commands/prune.ts +36 -0
  66. package/src/commands/rm.ts +125 -0
  67. package/src/commands/spawn.ts +169 -0
  68. package/src/index.ts +112 -0
  69. package/src/lib/config.ts +120 -0
  70. package/src/lib/git.ts +243 -0
  71. package/src/lib/output.ts +102 -0
  72. package/src/lib/paths.ts +108 -0
  73. package/src/lib/secrets.ts +193 -0
  74. package/src/lib/types.ts +69 -0
  75. package/tests/config.test.ts +102 -0
  76. package/tests/paths.test.ts +155 -0
  77. package/tests/secrets.test.ts +150 -0
  78. package/tsconfig.json +20 -0
  79. package/vitest.config.ts +15 -0
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Output utilities for VWT
3
+ *
4
+ * Provides consistent, colorful terminal output without external dependencies.
5
+ */
6
+ // ANSI color codes
7
+ const colors = {
8
+ reset: '\x1b[0m',
9
+ bold: '\x1b[1m',
10
+ dim: '\x1b[2m',
11
+ red: '\x1b[31m',
12
+ green: '\x1b[32m',
13
+ yellow: '\x1b[33m',
14
+ blue: '\x1b[34m',
15
+ magenta: '\x1b[35m',
16
+ cyan: '\x1b[36m',
17
+ white: '\x1b[37m',
18
+ gray: '\x1b[90m',
19
+ };
20
+ // Check if colors should be used
21
+ const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
22
+ function colorize(text, ...codes) {
23
+ if (!useColors)
24
+ return text;
25
+ return codes.join('') + text + colors.reset;
26
+ }
27
+ export const fmt = {
28
+ bold: (text) => colorize(text, colors.bold),
29
+ dim: (text) => colorize(text, colors.dim),
30
+ red: (text) => colorize(text, colors.red),
31
+ green: (text) => colorize(text, colors.green),
32
+ yellow: (text) => colorize(text, colors.yellow),
33
+ blue: (text) => colorize(text, colors.blue),
34
+ magenta: (text) => colorize(text, colors.magenta),
35
+ cyan: (text) => colorize(text, colors.cyan),
36
+ gray: (text) => colorize(text, colors.gray),
37
+ success: (text) => colorize(text, colors.green),
38
+ error: (text) => colorize(text, colors.red),
39
+ warn: (text) => colorize(text, colors.yellow),
40
+ info: (text) => colorize(text, colors.cyan),
41
+ path: (text) => colorize(text, colors.blue),
42
+ branch: (text) => colorize(text, colors.magenta),
43
+ };
44
+ export function log(message) {
45
+ console.log(message);
46
+ }
47
+ export function success(message) {
48
+ console.log(fmt.green('✓') + ' ' + message);
49
+ }
50
+ export function error(message) {
51
+ console.error(fmt.red('✗') + ' ' + message);
52
+ }
53
+ export function warn(message) {
54
+ console.log(fmt.yellow('⚠') + ' ' + message);
55
+ }
56
+ export function info(message) {
57
+ console.log(fmt.cyan('ℹ') + ' ' + message);
58
+ }
59
+ export function header(message) {
60
+ console.log('\n' + fmt.bold(message));
61
+ }
62
+ export function list(items, prefix = ' ') {
63
+ for (const item of items) {
64
+ console.log(prefix + '• ' + item);
65
+ }
66
+ }
67
+ export function table(rows, columnWidths) {
68
+ if (rows.length === 0)
69
+ return;
70
+ // Calculate column widths if not provided
71
+ const widths = columnWidths ?? rows[0].map((_, i) => Math.max(...rows.map(row => (row[i] ?? '').length)));
72
+ for (const row of rows) {
73
+ const paddedCells = row.map((cell, i) => (cell ?? '').padEnd(widths[i] ?? 0));
74
+ console.log(' ' + paddedCells.join(' '));
75
+ }
76
+ }
77
+ export function json(data) {
78
+ console.log(JSON.stringify(data, null, 2));
79
+ }
80
+ export function newline() {
81
+ console.log();
82
+ }
83
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Path utilities for VWT
3
+ */
4
+ /**
5
+ * Sanitize a branch name for use in filesystem paths
6
+ * - Replace slashes with double dashes
7
+ * - Remove or replace other problematic characters
8
+ */
9
+ export declare function sanitizeBranchName(branch: string): string;
10
+ /**
11
+ * Calculate the default worktree path
12
+ */
13
+ export declare function getDefaultWorktreePath(repoRoot: string, branch: string, options?: {
14
+ explicitPath?: string;
15
+ baseDir?: string;
16
+ repoName?: string;
17
+ }): string;
18
+ /**
19
+ * Check if a path is inside the .worktrees directory
20
+ */
21
+ export declare function isInsideWorktreesDir(targetPath: string, repoRoot: string): boolean;
22
+ /**
23
+ * Get relative path from repo root
24
+ */
25
+ export declare function getRelativePath(absolutePath: string, repoRoot: string): string;
26
+ /**
27
+ * Resolve a branch-or-path argument to a worktree path
28
+ */
29
+ export declare function resolveBranchOrPath(branchOrPath: string, worktrees: Array<{
30
+ branch: string | null;
31
+ path: string;
32
+ }>, repoRoot: string): {
33
+ path: string;
34
+ branch: string | null;
35
+ } | null;
36
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUzD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,MAAM,CAuBR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKlF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACzD,QAAQ,EAAE,MAAM,GACf;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAwBhD"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Path utilities for VWT
3
+ */
4
+ import path from 'node:path';
5
+ /**
6
+ * Sanitize a branch name for use in filesystem paths
7
+ * - Replace slashes with double dashes
8
+ * - Remove or replace other problematic characters
9
+ */
10
+ export function sanitizeBranchName(branch) {
11
+ return branch
12
+ .replace(/\//g, '--') // Replace slashes with double dashes
13
+ .replace(/[<>:"|?*\\]/g, '-') // Replace Windows-forbidden chars
14
+ .replace(/\s+/g, '-') // Replace whitespace
15
+ .replace(/^\.+/, '') // Remove leading dots
16
+ .replace(/\.+$/, '') // Remove trailing dots
17
+ .replace(/-+/g, '-') // Collapse multiple dashes
18
+ .replace(/^-+/, '') // Remove leading dashes
19
+ .replace(/-+$/, ''); // Remove trailing dashes
20
+ }
21
+ /**
22
+ * Calculate the default worktree path
23
+ */
24
+ export function getDefaultWorktreePath(repoRoot, branch, options) {
25
+ // Explicit path wins
26
+ if (options?.explicitPath) {
27
+ // If it's relative, resolve against CWD
28
+ if (!path.isAbsolute(options.explicitPath)) {
29
+ return path.resolve(options.explicitPath);
30
+ }
31
+ return options.explicitPath;
32
+ }
33
+ const sanitizedBranch = sanitizeBranchName(branch);
34
+ // Base directory specified
35
+ if (options?.baseDir) {
36
+ const repoName = options.repoName ?? path.basename(repoRoot);
37
+ const baseDir = path.isAbsolute(options.baseDir)
38
+ ? options.baseDir
39
+ : path.resolve(repoRoot, options.baseDir);
40
+ return path.join(baseDir, repoName, sanitizedBranch);
41
+ }
42
+ // Default: .worktrees/<branch> inside repo
43
+ return path.join(repoRoot, '.worktrees', sanitizedBranch);
44
+ }
45
+ /**
46
+ * Check if a path is inside the .worktrees directory
47
+ */
48
+ export function isInsideWorktreesDir(targetPath, repoRoot) {
49
+ const worktreesDir = path.join(repoRoot, '.worktrees');
50
+ const normalizedTarget = path.normalize(targetPath);
51
+ const normalizedWorktrees = path.normalize(worktreesDir);
52
+ return normalizedTarget.startsWith(normalizedWorktrees);
53
+ }
54
+ /**
55
+ * Get relative path from repo root
56
+ */
57
+ export function getRelativePath(absolutePath, repoRoot) {
58
+ return path.relative(repoRoot, absolutePath);
59
+ }
60
+ /**
61
+ * Resolve a branch-or-path argument to a worktree path
62
+ */
63
+ export function resolveBranchOrPath(branchOrPath, worktrees, repoRoot) {
64
+ // First, try to match by branch name
65
+ const byBranch = worktrees.find((w) => w.branch === branchOrPath);
66
+ if (byBranch) {
67
+ return { path: byBranch.path, branch: byBranch.branch };
68
+ }
69
+ // Try to match by path (absolute or relative)
70
+ const absolutePath = path.isAbsolute(branchOrPath)
71
+ ? branchOrPath
72
+ : path.resolve(repoRoot, branchOrPath);
73
+ const byPath = worktrees.find((w) => path.normalize(w.path) === path.normalize(absolutePath));
74
+ if (byPath) {
75
+ return { path: byPath.path, branch: byPath.branch };
76
+ }
77
+ // Try partial path match (end of path)
78
+ const byPartialPath = worktrees.find((w) => w.path.endsWith(branchOrPath));
79
+ if (byPartialPath) {
80
+ return { path: byPartialPath.path, branch: byPartialPath.branch };
81
+ }
82
+ return null;
83
+ }
84
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Secret file handling for VWT
3
+ *
4
+ * This module ensures that only git-ignored files are ever copied or symlinked.
5
+ * It provides a safety layer to prevent accidentally exposing tracked files.
6
+ */
7
+ import type { SecretMode } from './types.js';
8
+ export interface FileCheckResult {
9
+ path: string;
10
+ exists: boolean;
11
+ isTracked: boolean;
12
+ isIgnored: boolean;
13
+ safe: boolean;
14
+ reason?: string;
15
+ }
16
+ /**
17
+ * Check if a file is safe to copy/symlink
18
+ * A file is safe if:
19
+ * 1. It exists
20
+ * 2. It is NOT tracked by git
21
+ * 3. It IS ignored by git
22
+ */
23
+ export declare function checkFileSafety(filePath: string, repoRoot: string): FileCheckResult;
24
+ /**
25
+ * Expand glob patterns to actual file paths
26
+ */
27
+ export declare function expandIncludePatterns(patterns: string[], repoRoot: string): Promise<string[]>;
28
+ /**
29
+ * Get all safe files from include patterns
30
+ */
31
+ export declare function getSafeFiles(patterns: string[], repoRoot: string): Promise<{
32
+ safe: FileCheckResult[];
33
+ unsafe: FileCheckResult[];
34
+ }>;
35
+ /**
36
+ * Copy a file to the target directory, preserving relative path
37
+ */
38
+ export declare function copyFile(relativePath: string, sourceRoot: string, targetRoot: string): void;
39
+ /**
40
+ * Create a symlink in the target directory pointing to source
41
+ */
42
+ export declare function createSymlink(relativePath: string, sourceRoot: string, targetRoot: string): void;
43
+ /**
44
+ * Process files according to mode (copy or symlink)
45
+ */
46
+ export declare function processSecrets(mode: SecretMode, patterns: string[], sourceRoot: string, targetRoot: string): Promise<{
47
+ processed: string[];
48
+ skipped: FileCheckResult[];
49
+ }>;
50
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CA+BnF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CAgBjE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,IAAI,CAWN;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,IAAI,CAYN;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,CAAC,CA2B9D"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Secret file handling for VWT
3
+ *
4
+ * This module ensures that only git-ignored files are ever copied or symlinked.
5
+ * It provides a safety layer to prevent accidentally exposing tracked files.
6
+ */
7
+ import { existsSync, copyFileSync, symlinkSync, mkdirSync } from 'node:fs';
8
+ import path from 'node:path';
9
+ import { glob } from 'glob';
10
+ import { isTracked, isIgnored } from './git.js';
11
+ /**
12
+ * Check if a file is safe to copy/symlink
13
+ * A file is safe if:
14
+ * 1. It exists
15
+ * 2. It is NOT tracked by git
16
+ * 3. It IS ignored by git
17
+ */
18
+ export function checkFileSafety(filePath, repoRoot) {
19
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.join(repoRoot, filePath);
20
+ const relativePath = path.relative(repoRoot, absolutePath);
21
+ const result = {
22
+ path: relativePath,
23
+ exists: existsSync(absolutePath),
24
+ isTracked: false,
25
+ isIgnored: false,
26
+ safe: false,
27
+ };
28
+ if (!result.exists) {
29
+ result.reason = 'File does not exist';
30
+ return result;
31
+ }
32
+ result.isTracked = isTracked(relativePath, repoRoot);
33
+ if (result.isTracked) {
34
+ result.reason = 'File is tracked by git (would be committed)';
35
+ return result;
36
+ }
37
+ result.isIgnored = isIgnored(relativePath, repoRoot);
38
+ if (!result.isIgnored) {
39
+ result.reason = 'File is not ignored by git (could be accidentally committed)';
40
+ return result;
41
+ }
42
+ result.safe = true;
43
+ return result;
44
+ }
45
+ /**
46
+ * Expand glob patterns to actual file paths
47
+ */
48
+ export async function expandIncludePatterns(patterns, repoRoot) {
49
+ const allFiles = new Set();
50
+ for (const pattern of patterns) {
51
+ try {
52
+ const matches = await glob(pattern, {
53
+ cwd: repoRoot,
54
+ dot: true,
55
+ nodir: true,
56
+ });
57
+ for (const match of matches) {
58
+ allFiles.add(match);
59
+ }
60
+ }
61
+ catch {
62
+ // If glob fails, treat as literal path
63
+ if (existsSync(path.join(repoRoot, pattern))) {
64
+ allFiles.add(pattern);
65
+ }
66
+ }
67
+ }
68
+ return Array.from(allFiles).sort();
69
+ }
70
+ /**
71
+ * Get all safe files from include patterns
72
+ */
73
+ export async function getSafeFiles(patterns, repoRoot) {
74
+ const files = await expandIncludePatterns(patterns, repoRoot);
75
+ const safe = [];
76
+ const unsafe = [];
77
+ for (const file of files) {
78
+ const result = checkFileSafety(file, repoRoot);
79
+ if (result.safe) {
80
+ safe.push(result);
81
+ }
82
+ else if (result.exists) {
83
+ // Only report unsafe if file actually exists
84
+ unsafe.push(result);
85
+ }
86
+ }
87
+ return { safe, unsafe };
88
+ }
89
+ /**
90
+ * Copy a file to the target directory, preserving relative path
91
+ */
92
+ export function copyFile(relativePath, sourceRoot, targetRoot) {
93
+ const sourcePath = path.join(sourceRoot, relativePath);
94
+ const targetPath = path.join(targetRoot, relativePath);
95
+ // Create parent directories if needed
96
+ const targetDir = path.dirname(targetPath);
97
+ if (!existsSync(targetDir)) {
98
+ mkdirSync(targetDir, { recursive: true });
99
+ }
100
+ copyFileSync(sourcePath, targetPath);
101
+ }
102
+ /**
103
+ * Create a symlink in the target directory pointing to source
104
+ */
105
+ export function createSymlink(relativePath, sourceRoot, targetRoot) {
106
+ const sourcePath = path.join(sourceRoot, relativePath);
107
+ const targetPath = path.join(targetRoot, relativePath);
108
+ // Create parent directories if needed
109
+ const targetDir = path.dirname(targetPath);
110
+ if (!existsSync(targetDir)) {
111
+ mkdirSync(targetDir, { recursive: true });
112
+ }
113
+ // Use absolute path for symlink target for reliability
114
+ symlinkSync(sourcePath, targetPath);
115
+ }
116
+ /**
117
+ * Process files according to mode (copy or symlink)
118
+ */
119
+ export async function processSecrets(mode, patterns, sourceRoot, targetRoot) {
120
+ if (mode === 'none') {
121
+ return { processed: [], skipped: [] };
122
+ }
123
+ const { safe, unsafe } = await getSafeFiles(patterns, sourceRoot);
124
+ const processed = [];
125
+ for (const file of safe) {
126
+ try {
127
+ if (mode === 'copy') {
128
+ copyFile(file.path, sourceRoot, targetRoot);
129
+ }
130
+ else if (mode === 'symlink') {
131
+ createSymlink(file.path, sourceRoot, targetRoot);
132
+ }
133
+ processed.push(file.path);
134
+ }
135
+ catch (error) {
136
+ // Add to skipped with error reason
137
+ unsafe.push({
138
+ ...file,
139
+ safe: false,
140
+ reason: `Failed to ${mode}: ${error.message}`,
141
+ });
142
+ }
143
+ }
144
+ return { processed, skipped: unsafe };
145
+ }
146
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * VWT Configuration Types
3
+ */
4
+ export interface VwtConfig {
5
+ /** Base directory for worktrees (optional, defaults to .worktrees/) */
6
+ worktreeBaseDir?: string;
7
+ /** Default mode for secrets handling */
8
+ defaultMode: 'copy' | 'symlink' | 'none';
9
+ /** List of globs/paths to manage (e.g. [".env", ".env.*", "config/oauth*.json"]) */
10
+ include: string[];
11
+ /** Hook commands */
12
+ hooks?: {
13
+ postCreate?: string[];
14
+ };
15
+ /** Default agent command */
16
+ agentCommand?: string;
17
+ }
18
+ export interface VwtLocalConfig {
19
+ /** Machine-specific base directory override */
20
+ worktreeBaseDir?: string;
21
+ /** Additional include paths for this machine */
22
+ include?: string[];
23
+ /** Additional hooks for this machine */
24
+ hooks?: {
25
+ postCreate?: string[];
26
+ };
27
+ /** Override agent command */
28
+ agentCommand?: string;
29
+ }
30
+ export interface MergedConfig {
31
+ worktreeBaseDir?: string;
32
+ defaultMode: 'copy' | 'symlink' | 'none';
33
+ include: string[];
34
+ hooks: {
35
+ postCreate: string[];
36
+ };
37
+ agentCommand: string;
38
+ }
39
+ export interface WorktreeInfo {
40
+ worktree: string;
41
+ head: string;
42
+ branch?: string;
43
+ bare?: boolean;
44
+ detached?: boolean;
45
+ }
46
+ export interface WorktreeListItem {
47
+ branch: string | null;
48
+ path: string;
49
+ headShort: string;
50
+ dirty: boolean;
51
+ lastModified: Date | null;
52
+ }
53
+ export type SecretMode = 'copy' | 'symlink' | 'none';
54
+ export interface SpawnOptions {
55
+ branch: string;
56
+ isNew: boolean;
57
+ path?: string;
58
+ base?: string;
59
+ mode: SecretMode;
60
+ run?: string;
61
+ agent?: 'claude' | 'none';
62
+ }
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,oFAAoF;IACpF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oBAAoB;IACpB,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,4BAA4B;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,wCAAwC;IACxC,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;IACF,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE;QACL,UAAU,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC3B"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * VWT Configuration Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "cluttry",
3
+ "version": "1.0.0",
4
+ "description": "Cluttry - Git worktree management for parallel AI-agent sessions",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "cry": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "build:bun": "bun build src/index.ts --outdir dist --target node",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "start:bun": "bun run src/index.ts",
16
+ "test": "vitest run",
17
+ "test:bun": "bun test",
18
+ "test:watch": "vitest",
19
+ "test:coverage": "vitest run --coverage",
20
+ "lint": "eslint src --ext .ts",
21
+ "format": "prettier --write 'src/**/*.ts'",
22
+ "prepare": "npm run build"
23
+ },
24
+ "keywords": ["git", "worktree", "cli", "ai", "agent", "claude", "vibe", "bun"],
25
+ "license": "MIT",
26
+ "engines": {
27
+ "node": ">=18.0.0",
28
+ "bun": ">=1.0.0"
29
+ },
30
+ "dependencies": {
31
+ "commander": "^12.1.0",
32
+ "glob": "^10.3.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.10.0",
36
+ "@types/bun": "^1.1.0",
37
+ "typescript": "^5.3.0",
38
+ "vitest": "^1.0.0",
39
+ "prettier": "^3.1.0"
40
+ }
41
+ }