@mcadam/worktree 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 (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +315 -0
  3. package/bin/worktree.js +2 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +63 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/config.d.ts +2 -0
  9. package/dist/commands/config.d.ts.map +1 -0
  10. package/dist/commands/config.js +110 -0
  11. package/dist/commands/config.js.map +1 -0
  12. package/dist/commands/create.d.ts +2 -0
  13. package/dist/commands/create.d.ts.map +1 -0
  14. package/dist/commands/create.js +75 -0
  15. package/dist/commands/create.js.map +1 -0
  16. package/dist/commands/init.d.ts +2 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/init.js +90 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/list.d.ts +2 -0
  21. package/dist/commands/list.d.ts.map +1 -0
  22. package/dist/commands/list.js +82 -0
  23. package/dist/commands/list.js.map +1 -0
  24. package/dist/components/WorktreeList.d.ts +10 -0
  25. package/dist/components/WorktreeList.d.ts.map +1 -0
  26. package/dist/components/WorktreeList.js +41 -0
  27. package/dist/components/WorktreeList.js.map +1 -0
  28. package/dist/config/detector.d.ts +4 -0
  29. package/dist/config/detector.d.ts.map +1 -0
  30. package/dist/config/detector.js +34 -0
  31. package/dist/config/detector.js.map +1 -0
  32. package/dist/config/manager.d.ts +19 -0
  33. package/dist/config/manager.d.ts.map +1 -0
  34. package/dist/config/manager.js +73 -0
  35. package/dist/config/manager.js.map +1 -0
  36. package/dist/config/schema.d.ts +77 -0
  37. package/dist/config/schema.d.ts.map +1 -0
  38. package/dist/config/schema.js +19 -0
  39. package/dist/config/schema.js.map +1 -0
  40. package/dist/utils/gh.d.ts +13 -0
  41. package/dist/utils/gh.d.ts.map +1 -0
  42. package/dist/utils/gh.js +41 -0
  43. package/dist/utils/gh.js.map +1 -0
  44. package/dist/utils/git.d.ts +14 -0
  45. package/dist/utils/git.d.ts.map +1 -0
  46. package/dist/utils/git.js +91 -0
  47. package/dist/utils/git.js.map +1 -0
  48. package/dist/utils/sanitize.d.ts +3 -0
  49. package/dist/utils/sanitize.d.ts.map +1 -0
  50. package/dist/utils/sanitize.js +13 -0
  51. package/dist/utils/sanitize.js.map +1 -0
  52. package/package.json +68 -0
@@ -0,0 +1,90 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { render, Box, Text } from 'ink';
4
+ import TextInput from 'ink-text-input';
5
+ import chalk from 'chalk';
6
+ import { configManager } from '../config/manager.js';
7
+ import { getRepoName } from '../config/detector.js';
8
+ function InitForm({ gitRoot, defaultName, onComplete }) {
9
+ const [step, setStep] = useState(0);
10
+ const [name, setName] = useState(defaultName);
11
+ const [prefix, setPrefix] = useState('');
12
+ const [basePath, setBasePath] = useState('../');
13
+ const [envPath, setEnvPath] = useState('');
14
+ const [installCommand, setInstallCommand] = useState('');
15
+ const [ideCommand, setIdeCommand] = useState('');
16
+ const handleSubmit = (value) => {
17
+ switch (step) {
18
+ case 0: // Name
19
+ setName(value || defaultName);
20
+ setStep(1);
21
+ break;
22
+ case 1: // Prefix
23
+ setPrefix(value);
24
+ setStep(2);
25
+ break;
26
+ case 2: // Base path
27
+ setBasePath(value || '../');
28
+ setStep(3);
29
+ break;
30
+ case 3: // Env path
31
+ setEnvPath(value);
32
+ setStep(4);
33
+ break;
34
+ case 4: // Install command
35
+ setInstallCommand(value);
36
+ setStep(5);
37
+ break;
38
+ case 5: // IDE command
39
+ setIdeCommand(value);
40
+ const config = {
41
+ name,
42
+ prefix,
43
+ basePath: basePath || undefined,
44
+ envPath: envPath || undefined,
45
+ installCommand: installCommand || undefined,
46
+ ideCommand: ideCommand || undefined,
47
+ };
48
+ onComplete(config);
49
+ break;
50
+ }
51
+ };
52
+ const fields = [
53
+ { label: 'Repository name', value: name, placeholder: defaultName },
54
+ { label: 'Worktree prefix (e.g., "fe-", "be-")', value: prefix, placeholder: 'prefix-' },
55
+ { label: 'Base path for worktrees', value: basePath, placeholder: '../' },
56
+ { label: '.env file to copy (optional)', value: envPath, placeholder: '.env.local' },
57
+ { label: 'Install command (optional)', value: installCommand, placeholder: 'pnpm install' },
58
+ { label: 'IDE command (optional)', value: ideCommand, placeholder: 'cursor' },
59
+ ];
60
+ const currentField = fields[step];
61
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Configure repository: ", gitRoot] }), _jsxs(Box, { marginY: 1, children: [_jsxs(Text, { children: [currentField.label, ": "] }), _jsx(TextInput, { value: step === 0 ? name :
62
+ step === 1 ? prefix :
63
+ step === 2 ? basePath :
64
+ step === 3 ? envPath :
65
+ step === 4 ? installCommand :
66
+ ideCommand, onChange: step === 0 ? setName :
67
+ step === 1 ? setPrefix :
68
+ step === 2 ? setBasePath :
69
+ step === 3 ? setEnvPath :
70
+ step === 4 ? setInstallCommand :
71
+ setIdeCommand, onSubmit: handleSubmit, placeholder: currentField.placeholder })] }), _jsx(Text, { dimColor: true, children: "Press Enter to continue, Ctrl+C to cancel" })] }));
72
+ }
73
+ export async function initCommand(gitRoot) {
74
+ const defaultName = await getRepoName(gitRoot);
75
+ return new Promise((resolve) => {
76
+ const { unmount } = render(_jsx(InitForm, { gitRoot: gitRoot, defaultName: defaultName, onComplete: async (config) => {
77
+ unmount();
78
+ await configManager.setRepoConfig(gitRoot, config);
79
+ console.log(chalk.green(`\n✨ Repository configured successfully!`));
80
+ console.log(chalk.gray(`Configuration saved for: ${config.name}`));
81
+ console.log(chalk.cyan(`🚀 You're all set! Run 'worktree <branch>' to create your first worktree!`));
82
+ resolve();
83
+ }, onCancel: () => {
84
+ unmount();
85
+ console.log(chalk.yellow('Configuration cancelled'));
86
+ resolve();
87
+ } }));
88
+ });
89
+ }
90
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function listCommand(currentGitRoot: string): Promise<void>;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.tsx"],"names":[],"mappings":"AA2EA,wBAAsB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CvE"}
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { render, Box, Text } from 'ink';
4
+ import chalk from 'chalk';
5
+ import { configManager } from '../config/manager.js';
6
+ import { listWorktrees, removeWorktree } from '../utils/git.js';
7
+ import { enrichWorktreesWithPRInfo } from '../utils/gh.js';
8
+ import { WorktreeList } from '../components/WorktreeList.js';
9
+ function ListApp({ repos }) {
10
+ const [currentRepoIndex] = useState(0);
11
+ const [isDeleting, setIsDeleting] = useState(false);
12
+ const handleDelete = async (paths) => {
13
+ setIsDeleting(true);
14
+ const currentRepo = repos[currentRepoIndex];
15
+ console.log(chalk.yellow(`\n🗑️ Deleting ${paths.length} worktree${paths.length > 1 ? 's' : ''}...`));
16
+ let successCount = 0;
17
+ for (const path of paths) {
18
+ try {
19
+ await removeWorktree(path, currentRepo.repoPath);
20
+ successCount++;
21
+ console.log(chalk.green(` ✓ Removed: ${path.split('/').pop()}`));
22
+ }
23
+ catch (error) {
24
+ console.error(chalk.red(` ✗ Failed to remove ${path}: ${error}`));
25
+ }
26
+ }
27
+ if (successCount > 0) {
28
+ console.log(chalk.cyan(`\n✅ Successfully deleted ${successCount} worktree${successCount > 1 ? 's' : ''}!`));
29
+ console.log(chalk.gray(`💪 Workspace cleaned up and ready to go!`));
30
+ }
31
+ // Refresh the list after deletion
32
+ setTimeout(() => process.exit(0), 1500);
33
+ };
34
+ if (repos.length === 0) {
35
+ return (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No configured repositories found" }) }));
36
+ }
37
+ if (isDeleting) {
38
+ return (_jsx(Box, { children: _jsx(Text, { color: "cyan", children: "Deleting worktrees..." }) }));
39
+ }
40
+ return (_jsx(Box, { flexDirection: "column", children: repos.map((repo) => (_jsx(WorktreeList, { worktrees: repo.worktrees, repoName: repo.repoName, repoPath: repo.repoPath, onDelete: handleDelete }, repo.repoPath))) }));
41
+ }
42
+ export async function listCommand(currentGitRoot) {
43
+ const allRepoConfigs = await configManager.getAllRepoConfigs();
44
+ const repos = [];
45
+ // Add current repo first if configured
46
+ const currentRepoConfig = allRepoConfigs[currentGitRoot];
47
+ if (currentRepoConfig) {
48
+ const worktrees = await listWorktrees(currentGitRoot);
49
+ await enrichWorktreesWithPRInfo(worktrees, currentGitRoot);
50
+ repos.push({
51
+ repoPath: currentGitRoot,
52
+ repoName: currentRepoConfig.name,
53
+ worktrees,
54
+ });
55
+ }
56
+ // Add other configured repos
57
+ for (const [repoPath, config] of Object.entries(allRepoConfigs)) {
58
+ if (repoPath === currentGitRoot)
59
+ continue;
60
+ try {
61
+ const worktrees = await listWorktrees(repoPath);
62
+ await enrichWorktreesWithPRInfo(worktrees, repoPath);
63
+ repos.push({
64
+ repoPath,
65
+ repoName: config.name,
66
+ worktrees,
67
+ });
68
+ }
69
+ catch (error) {
70
+ // Skip repos that might have been deleted or are inaccessible
71
+ console.warn(chalk.yellow(`Warning: Could not access ${config.name} at ${repoPath}`));
72
+ }
73
+ }
74
+ if (repos.length === 0) {
75
+ console.log(chalk.yellow('\n📦 No configured repositories found'));
76
+ console.log(chalk.cyan('👉 Run "worktree init" to configure the current repository'));
77
+ console.log(chalk.gray(' Then create your first worktree with "worktree <branch>"!'));
78
+ return;
79
+ }
80
+ render(_jsx(ListApp, { repos: repos }));
81
+ }
82
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { Worktree } from '../utils/git.js';
2
+ interface WorktreeListProps {
3
+ worktrees: Worktree[];
4
+ repoName: string;
5
+ repoPath: string;
6
+ onDelete: (paths: string[]) => void;
7
+ }
8
+ export declare function WorktreeList({ worktrees, repoName, repoPath, onDelete }: WorktreeListProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=WorktreeList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorktreeList.d.ts","sourceRoot":"","sources":["../../src/components/WorktreeList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE1C,UAAU,iBAAiB;IACzB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACpC;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CA4E1F"}
@@ -0,0 +1,41 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Text, useInput, useApp } from 'ink';
4
+ export function WorktreeList({ worktrees, repoName, repoPath, onDelete }) {
5
+ const [selectedIndex, setSelectedIndex] = useState(0);
6
+ const [checkedItems, setCheckedItems] = useState(new Set());
7
+ const { exit } = useApp();
8
+ const filteredWorktrees = worktrees.filter((w) => !w.isMain);
9
+ useInput((input, key) => {
10
+ if (key.upArrow) {
11
+ setSelectedIndex((prev) => Math.max(0, prev - 1));
12
+ }
13
+ else if (key.downArrow) {
14
+ setSelectedIndex((prev) => Math.min(filteredWorktrees.length - 1, prev + 1));
15
+ }
16
+ else if (input === ' ') {
17
+ const worktree = filteredWorktrees[selectedIndex];
18
+ if (worktree) {
19
+ const newChecked = new Set(checkedItems);
20
+ if (newChecked.has(worktree.path)) {
21
+ newChecked.delete(worktree.path);
22
+ }
23
+ else {
24
+ newChecked.add(worktree.path);
25
+ }
26
+ setCheckedItems(newChecked);
27
+ }
28
+ }
29
+ else if (key.return && checkedItems.size > 0) {
30
+ onDelete(Array.from(checkedItems));
31
+ }
32
+ else if (input === 'q') {
33
+ exit();
34
+ }
35
+ });
36
+ if (filteredWorktrees.length === 0) {
37
+ return (_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsxs(Text, { color: "yellow", children: ["No worktrees found for ", repoName] }) }));
38
+ }
39
+ return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsxs(Text, { bold: true, color: "cyan", children: [repoName, " (", repoPath, ")"] }) }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: filteredWorktrees.map((worktree, index) => (_jsxs(Box, { children: [_jsx(Text, { color: index === selectedIndex ? 'cyan' : 'white', children: index === selectedIndex ? '❯' : ' ' }), _jsx(Text, { children: " " }), _jsx(Text, { children: checkedItems.has(worktree.path) ? '☑' : '☐' }), _jsx(Text, { children: " " }), _jsx(Text, { color: index === selectedIndex ? 'cyan' : 'white', children: worktree.branch || 'detached' }), worktree.isPushed && (_jsx(Text, { color: "green", children: " \u2713 remote" })), worktree.hasPR && (_jsxs(Text, { color: "magenta", children: [" \uD83D\uDD00 PR #", worktree.prNumber] })), !worktree.isPushed && (_jsx(Text, { color: "yellow", children: " \u26A0\uFE0F local only" }))] }, worktree.path))) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["[Space] Select [Enter] Delete Selected (", checkedItems.size, ") [Q] Quit"] }) })] }));
40
+ }
41
+ //# sourceMappingURL=WorktreeList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorktreeList.js","sourceRoot":"","sources":["../../src/components/WorktreeList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function getGitRoot(cwd?: string): Promise<string | null>;
2
+ export declare function getRepoName(gitRoot: string): Promise<string>;
3
+ export declare function isGitRepo(dir?: string): Promise<boolean>;
4
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/config/detector.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOpF;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBlE;AAED,wBAAsB,SAAS,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAG7E"}
@@ -0,0 +1,34 @@
1
+ import { execa } from 'execa';
2
+ import path from 'path';
3
+ export async function getGitRoot(cwd = process.cwd()) {
4
+ try {
5
+ const { stdout } = await execa('git', ['rev-parse', '--show-toplevel'], { cwd });
6
+ return stdout.trim();
7
+ }
8
+ catch {
9
+ return null;
10
+ }
11
+ }
12
+ export async function getRepoName(gitRoot) {
13
+ try {
14
+ const { stdout } = await execa('git', ['remote', 'get-url', 'origin'], { cwd: gitRoot });
15
+ const url = stdout.trim();
16
+ // Extract repo name from URL
17
+ // Handle both SSH and HTTPS URLs
18
+ const match = url.match(/[/:]([\w-]+)\/([\w-]+?)(\.git)?$/);
19
+ if (match) {
20
+ return match[2];
21
+ }
22
+ // Fallback to directory name
23
+ return path.basename(gitRoot);
24
+ }
25
+ catch {
26
+ // If no remote, use directory name
27
+ return path.basename(gitRoot);
28
+ }
29
+ }
30
+ export async function isGitRepo(dir = process.cwd()) {
31
+ const gitRoot = await getGitRoot(dir);
32
+ return gitRoot !== null;
33
+ }
34
+ //# sourceMappingURL=detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/config/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC1D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAChF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAA;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe;IAC/C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAA;QACxF,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QAEzB,6BAA6B;QAC7B,iCAAiC;QACjC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;QAC3D,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,6BAA6B;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACzD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAA;IACrC,OAAO,OAAO,KAAK,IAAI,CAAA;AACzB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { GlobalConfig, RepoConfig } from './schema.js';
2
+ export declare class ConfigManager {
3
+ private config;
4
+ load(): Promise<GlobalConfig>;
5
+ save(): Promise<void>;
6
+ getRepoConfig(repoPath: string): Promise<RepoConfig | null>;
7
+ setRepoConfig(repoPath: string, repoConfig: RepoConfig): Promise<void>;
8
+ removeRepoConfig(repoPath: string): Promise<void>;
9
+ getAllRepoConfigs(): Promise<Record<string, RepoConfig>>;
10
+ getEffectiveConfig(repoConfig: RepoConfig | null): {
11
+ basePath: string;
12
+ installCommand: string;
13
+ ideCommand: string;
14
+ envPath?: string;
15
+ };
16
+ updateDefaults(defaults: Partial<Pick<GlobalConfig, 'defaultBasePath' | 'defaultInstallCommand' | 'defaultIdeCommand'>>): Promise<void>;
17
+ }
18
+ export declare const configManager: ConfigManager;
19
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAsB,UAAU,EAAE,MAAM,aAAa,CAAA;AAI1E,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAEpC,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC;IAqB7B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAK3D,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAK9D,kBAAkB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,GAAG;QACjD,QAAQ,EAAE,MAAM,CAAA;QAChB,cAAc,EAAE,MAAM,CAAA;QACtB,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB;IAaK,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,iBAAiB,GAAG,uBAAuB,GAAG,mBAAmB,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAM9I;AAED,eAAO,MAAM,aAAa,eAAsB,CAAA"}
@@ -0,0 +1,73 @@
1
+ import fs from 'fs-extra';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import { GlobalConfigSchema } from './schema.js';
5
+ const CONFIG_PATH = path.join(os.homedir(), '.worktreerc.json');
6
+ export class ConfigManager {
7
+ config = null;
8
+ async load() {
9
+ if (this.config)
10
+ return this.config;
11
+ try {
12
+ const exists = await fs.pathExists(CONFIG_PATH);
13
+ if (!exists) {
14
+ this.config = GlobalConfigSchema.parse({});
15
+ await this.save();
16
+ return this.config;
17
+ }
18
+ const data = await fs.readJson(CONFIG_PATH);
19
+ this.config = GlobalConfigSchema.parse(data);
20
+ return this.config;
21
+ }
22
+ catch (error) {
23
+ console.error('Error loading config:', error);
24
+ this.config = GlobalConfigSchema.parse({});
25
+ return this.config;
26
+ }
27
+ }
28
+ async save() {
29
+ if (!this.config) {
30
+ throw new Error('No config loaded');
31
+ }
32
+ await fs.outputJson(CONFIG_PATH, this.config, { spaces: 2 });
33
+ }
34
+ async getRepoConfig(repoPath) {
35
+ const config = await this.load();
36
+ return config.repos[repoPath] || null;
37
+ }
38
+ async setRepoConfig(repoPath, repoConfig) {
39
+ const config = await this.load();
40
+ config.repos[repoPath] = repoConfig;
41
+ this.config = config;
42
+ await this.save();
43
+ }
44
+ async removeRepoConfig(repoPath) {
45
+ const config = await this.load();
46
+ delete config.repos[repoPath];
47
+ this.config = config;
48
+ await this.save();
49
+ }
50
+ async getAllRepoConfigs() {
51
+ const config = await this.load();
52
+ return config.repos;
53
+ }
54
+ getEffectiveConfig(repoConfig) {
55
+ if (!this.config) {
56
+ throw new Error('Config not loaded');
57
+ }
58
+ return {
59
+ basePath: repoConfig?.basePath || this.config.defaultBasePath,
60
+ installCommand: repoConfig?.installCommand || this.config.defaultInstallCommand,
61
+ ideCommand: repoConfig?.ideCommand || this.config.defaultIdeCommand,
62
+ envPath: repoConfig?.envPath,
63
+ };
64
+ }
65
+ async updateDefaults(defaults) {
66
+ const config = await this.load();
67
+ Object.assign(config, defaults);
68
+ this.config = config;
69
+ await this.save();
70
+ }
71
+ }
72
+ export const configManager = new ConfigManager();
73
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/config/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { z } from 'zod';
2
+ export declare const RepoConfigSchema: z.ZodObject<{
3
+ name: z.ZodString;
4
+ prefix: z.ZodString;
5
+ basePath: z.ZodOptional<z.ZodString>;
6
+ envPath: z.ZodOptional<z.ZodString>;
7
+ installCommand: z.ZodOptional<z.ZodString>;
8
+ ideCommand: z.ZodOptional<z.ZodString>;
9
+ }, "strip", z.ZodTypeAny, {
10
+ name: string;
11
+ prefix: string;
12
+ basePath?: string | undefined;
13
+ envPath?: string | undefined;
14
+ installCommand?: string | undefined;
15
+ ideCommand?: string | undefined;
16
+ }, {
17
+ name: string;
18
+ prefix: string;
19
+ basePath?: string | undefined;
20
+ envPath?: string | undefined;
21
+ installCommand?: string | undefined;
22
+ ideCommand?: string | undefined;
23
+ }>;
24
+ export declare const GlobalConfigSchema: z.ZodObject<{
25
+ defaultBasePath: z.ZodDefault<z.ZodString>;
26
+ defaultInstallCommand: z.ZodDefault<z.ZodString>;
27
+ defaultIdeCommand: z.ZodDefault<z.ZodString>;
28
+ repos: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
29
+ name: z.ZodString;
30
+ prefix: z.ZodString;
31
+ basePath: z.ZodOptional<z.ZodString>;
32
+ envPath: z.ZodOptional<z.ZodString>;
33
+ installCommand: z.ZodOptional<z.ZodString>;
34
+ ideCommand: z.ZodOptional<z.ZodString>;
35
+ }, "strip", z.ZodTypeAny, {
36
+ name: string;
37
+ prefix: string;
38
+ basePath?: string | undefined;
39
+ envPath?: string | undefined;
40
+ installCommand?: string | undefined;
41
+ ideCommand?: string | undefined;
42
+ }, {
43
+ name: string;
44
+ prefix: string;
45
+ basePath?: string | undefined;
46
+ envPath?: string | undefined;
47
+ installCommand?: string | undefined;
48
+ ideCommand?: string | undefined;
49
+ }>>>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ defaultBasePath: string;
52
+ defaultInstallCommand: string;
53
+ defaultIdeCommand: string;
54
+ repos: Record<string, {
55
+ name: string;
56
+ prefix: string;
57
+ basePath?: string | undefined;
58
+ envPath?: string | undefined;
59
+ installCommand?: string | undefined;
60
+ ideCommand?: string | undefined;
61
+ }>;
62
+ }, {
63
+ defaultBasePath?: string | undefined;
64
+ defaultInstallCommand?: string | undefined;
65
+ defaultIdeCommand?: string | undefined;
66
+ repos?: Record<string, {
67
+ name: string;
68
+ prefix: string;
69
+ basePath?: string | undefined;
70
+ envPath?: string | undefined;
71
+ installCommand?: string | undefined;
72
+ ideCommand?: string | undefined;
73
+ }> | undefined;
74
+ }>;
75
+ export type RepoConfig = z.infer<typeof RepoConfigSchema>;
76
+ export type GlobalConfig = z.infer<typeof GlobalConfigSchema>;
77
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAO3B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ7B,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ export const RepoConfigSchema = z.object({
3
+ name: z.string().describe('Repository name for display'),
4
+ prefix: z.string().describe('Prefix for worktree directories (e.g., "fe-", "be-")'),
5
+ basePath: z.string().optional().describe('Directory to create worktrees in'),
6
+ envPath: z.string().optional().describe('.env file to copy to new worktrees'),
7
+ installCommand: z.string().optional().describe('Command to run after creating worktree'),
8
+ ideCommand: z.string().optional().describe('IDE command to open worktree'),
9
+ });
10
+ export const GlobalConfigSchema = z.object({
11
+ defaultBasePath: z.string().default('../').describe('Default directory for worktrees'),
12
+ defaultInstallCommand: z
13
+ .string()
14
+ .default('pnpm install')
15
+ .describe('Default install command'),
16
+ defaultIdeCommand: z.string().default('cursor').describe('Default IDE command'),
17
+ repos: z.record(z.string(), RepoConfigSchema).default({}).describe('Repository configurations'),
18
+ });
19
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;IACxD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;IACnF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;IAC5E,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;IAC7E,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACxF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;CAC3E,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IACtF,qBAAqB,EAAE,CAAC;SACrB,MAAM,EAAE;SACR,OAAO,CAAC,cAAc,CAAC;SACvB,QAAQ,CAAC,yBAAyB,CAAC;IACtC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC;IAC/E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;CAChG,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ interface PRInfo {
2
+ number: number;
3
+ headRefName: string;
4
+ state: string;
5
+ }
6
+ export declare function isGhInstalled(): Promise<boolean>;
7
+ export declare function getPRInfo(gitRoot: string): Promise<Map<string, PRInfo>>;
8
+ export declare function enrichWorktreesWithPRInfo(worktrees: Array<{
9
+ branch?: string;
10
+ [key: string]: any;
11
+ }>, gitRoot: string): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=gh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh.d.ts","sourceRoot":"","sources":["../../src/utils/gh.ts"],"names":[],"mappings":"AAEA,UAAU,MAAM;IACd,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAOtD;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyB7E;AAED,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,KAAK,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC,EACzD,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAYf"}
@@ -0,0 +1,41 @@
1
+ import { execa } from 'execa';
2
+ export async function isGhInstalled() {
3
+ try {
4
+ await execa('which', ['gh']);
5
+ return true;
6
+ }
7
+ catch {
8
+ return false;
9
+ }
10
+ }
11
+ export async function getPRInfo(gitRoot) {
12
+ const prMap = new Map();
13
+ if (!(await isGhInstalled())) {
14
+ return prMap;
15
+ }
16
+ try {
17
+ const { stdout } = await execa('gh', ['pr', 'list', '--json', 'number,headRefName,state', '--limit', '100'], { cwd: gitRoot });
18
+ const prs = JSON.parse(stdout);
19
+ for (const pr of prs) {
20
+ prMap.set(pr.headRefName, pr);
21
+ }
22
+ }
23
+ catch (error) {
24
+ // gh might not be authenticated or repo might not have GitHub remote
25
+ // Silently fail and return empty map
26
+ }
27
+ return prMap;
28
+ }
29
+ export async function enrichWorktreesWithPRInfo(worktrees, gitRoot) {
30
+ const prInfo = await getPRInfo(gitRoot);
31
+ for (const worktree of worktrees) {
32
+ if (worktree.branch) {
33
+ const pr = prInfo.get(worktree.branch);
34
+ if (pr) {
35
+ worktree.hasPR = true;
36
+ worktree.prNumber = pr.number;
37
+ }
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=gh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh.js","sourceRoot":"","sources":["../../src/utils/gh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAQ7B,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;QAC5B,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IAEvC,IAAI,CAAC,CAAC,MAAM,aAAa,EAAE,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,IAAI,EACJ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,0BAA0B,EAAE,SAAS,EAAE,KAAK,CAAC,EACtE,EAAE,GAAG,EAAE,OAAO,EAAE,CACjB,CAAA;QAED,MAAM,GAAG,GAAa,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAExC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qEAAqE;QACrE,qCAAqC;IACvC,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,SAAyD,EACzD,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;IAEvC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YACtC,IAAI,EAAE,EAAE,CAAC;gBACP,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAA;gBACrB,QAAQ,CAAC,QAAQ,GAAG,EAAE,CAAC,MAAM,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface Worktree {
2
+ path: string;
3
+ branch: string;
4
+ commit: string;
5
+ isMain: boolean;
6
+ isPushed?: boolean;
7
+ hasPR?: boolean;
8
+ prNumber?: number;
9
+ }
10
+ export declare function createWorktree(basePath: string, worktreeName: string, branchName: string, gitRoot: string): Promise<void>;
11
+ export declare function listWorktrees(gitRoot: string): Promise<Worktree[]>;
12
+ export declare function removeWorktree(worktreePath: string, gitRoot: string): Promise<void>;
13
+ export declare function getAllBranches(gitRoot: string): Promise<string[]>;
14
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAqDxE;AAED,wBAAsB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOvE"}