@jasonfutch/worktree-manager 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jason Futch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # Worktree Manager TUI/CLI
2
+
3
+ A terminal app for managing git worktrees with AI assistance.
4
+
5
+ ## Features
6
+
7
+ - **TUI Interface** - Full terminal UI built with blessed
8
+ - **Git Worktree Management** - Create, list, and remove worktrees
9
+ - **IDE Integration** - Open worktrees in VS Code, Cursor, Zed, and more
10
+ - **AI Integration** - Launch Claude, Gemini, or Codex in any worktree
11
+ - **Parallel Development** - Work on multiple features simultaneously
12
+ - **Auto-Update Notifications** - Get notified when a new version is available
13
+
14
+ ## Requirements
15
+
16
+ - Node.js >= 18
17
+ - Git
18
+ - Optional: VS Code, Cursor, Zed, Claude CLI
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install -g @jasonfutch/worktree-manager
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Interactive TUI Mode
29
+
30
+ ```bash
31
+ # Launch TUI in current directory
32
+ wtm
33
+
34
+ # Launch TUI for a specific repo
35
+ wtm /path/to/repo
36
+ ```
37
+
38
+ ### Keybindings
39
+
40
+ | Key | Action |
41
+ | ------- | ------------------------- |
42
+ | `↑/k` | Move up |
43
+ | `↓/j` | Move down |
44
+ | `Enter` | Select/Details |
45
+ | `n` | Create new worktree |
46
+ | `d` | Delete worktree |
47
+ | `e` | Open in editor (selector) |
48
+ | `t` | Open terminal |
49
+ | `a` | Launch AI tool (selector) |
50
+ | `r` | Refresh |
51
+ | `?` | Help |
52
+ | `q` | Quit |
53
+
54
+ ### CLI Commands
55
+
56
+ ```bash
57
+ # List all worktrees
58
+ wtm list
59
+ wtm list /path/to/repo
60
+
61
+ # Create a new worktree
62
+ wtm create feature/my-feature
63
+ wtm create feature/my-feature -b main
64
+ wtm create feature/my-feature -p /custom/path
65
+
66
+ # Remove a worktree
67
+ wtm remove feature/my-feature
68
+ wtm remove feature/my-feature --force
69
+
70
+ # Open worktree in editor
71
+ wtm open feature/my-feature
72
+ wtm open main -e cursor
73
+ # Editors: code, cursor, zed, webstorm, subl, nvim
74
+
75
+ # Open terminal in worktree
76
+ wtm terminal feature/my-feature
77
+ wtm term main
78
+
79
+ # Launch AI tool in worktree
80
+ wtm ai feature/my-feature
81
+ wtm ai main -t gemini
82
+ # Tools: claude, gemini, codex
83
+
84
+ # Update to latest version
85
+ wtm update
86
+
87
+ # Show detailed help
88
+ wtm help
89
+ ```
90
+
91
+ ## How It Works
92
+
93
+ 1. **Worktrees** - Uses `git worktree` to create isolated working directories for each branch
94
+ 2. **Parallel Development** - Each worktree is independent, allowing you to run different AI coding sessions
95
+ 3. **IDE Integration** - Opens editors in the worktree directory so your AI assistant has the right context
96
+ 4. **Terminal Sessions** - Opens new terminal windows/tabs in the worktree directory
97
+
98
+ ## Updating
99
+
100
+ The CLI automatically checks for updates once per day and notifies you when a new version is available:
101
+
102
+ ```
103
+ ╭─────────────────────────────────────────────────╮
104
+ │ │
105
+ │ Update available 1.0.0 → 1.1.0 │
106
+ │ Run npm i -g @jasonfutch/worktree-manager │
107
+ │ │
108
+ ╰─────────────────────────────────────────────────╯
109
+ ```
110
+
111
+ You can also manually update at any time:
112
+
113
+ ```bash
114
+ wtm update
115
+ ```
116
+
117
+ ## Screenshots
118
+
119
+ ### Main Interface
120
+
121
+ ![Main TUI](assets/screenshots/main-view.png)
122
+
123
+ ### Create New Worktree
124
+
125
+ ![Create Worktree](assets/screenshots/create-worktree.png)
126
+
127
+ ### Open In Editor
128
+
129
+ ![Editor Selector](assets/screenshots/editor-selector.png)
130
+
131
+ ### Open In AI Tool
132
+
133
+ ![AI Selector](assets/screenshots/ai-selector.png)
134
+
135
+ ---
136
+
137
+ ## Development
138
+
139
+ ### Installation from Source
140
+
141
+ ```bash
142
+ git clone https://github.com/jasonfutch/worktree-manager
143
+ cd worktree-manager
144
+ npm install
145
+ npm run build
146
+
147
+ # Link globally for testing
148
+ npm link
149
+ ```
150
+
151
+ ### Commands
152
+
153
+ ```bash
154
+ npm run dev # Run in development mode
155
+ npm run build # Build TypeScript
156
+ npm run clean # Clean build artifacts
157
+ ```
158
+
159
+ ## Architecture
160
+
161
+ ```
162
+ worktree-manager/
163
+ ├── src/
164
+ │ ├── index.ts # CLI entry point
165
+ │ ├── types.ts # TypeScript types
166
+ │ ├── errors.ts # Custom error classes
167
+ │ ├── constants.ts # Application constants
168
+ │ ├── version.ts # Version from package.json
169
+ │ ├── git/
170
+ │ │ └── worktree.ts # Git worktree operations
171
+ │ ├── tui/
172
+ │ │ └── app.ts # Blessed TUI application
173
+ │ └── utils/
174
+ │ ├── helpers.ts # Utility functions
175
+ │ ├── shell.ts # Shell escaping utilities
176
+ │ ├── launch.ts # Editor/terminal launchers
177
+ │ └── checks.ts # Startup validation
178
+ ├── dist/ # Compiled output
179
+ ├── package.json
180
+ ├── tsconfig.json
181
+ └── README.md
182
+ ```
183
+
184
+ ## License
185
+
186
+ MIT
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Constants used throughout the worktree manager application
3
+ */
4
+ /**
5
+ * UI-related constants
6
+ */
7
+ export declare const UI: {
8
+ /** Maximum length for branch names in list display */
9
+ readonly BRANCH_TRUNCATE_LENGTH: 30;
10
+ /** Height of the help modal in lines */
11
+ readonly HELP_MODAL_HEIGHT: 26;
12
+ /** Height of the create worktree form in lines */
13
+ readonly CREATE_FORM_HEIGHT: 20;
14
+ /** Width of modal dialogs */
15
+ readonly MODAL_WIDTH: 50;
16
+ /** Width of the editor/AI selection dialog */
17
+ readonly SELECTOR_WIDTH: 40;
18
+ /** Height of the editor selection dialog */
19
+ readonly EDITOR_SELECTOR_HEIGHT: 12;
20
+ /** Height of the AI tool selection dialog */
21
+ readonly AI_SELECTOR_HEIGHT: 9;
22
+ };
23
+ /**
24
+ * Git-related constants
25
+ */
26
+ export declare const GIT: {
27
+ /** Length of short SHA commit hash */
28
+ readonly SHORT_SHA_LENGTH: 7;
29
+ /** Default base branch name */
30
+ readonly DEFAULT_BASE_BRANCH: "main";
31
+ /** Directory name for worktrees relative to repo */
32
+ readonly WORKTREES_DIR: "worktrees";
33
+ /** Branches that should never be offered for deletion */
34
+ readonly PROTECTED_BRANCHES: readonly ["main", "master", "production", "prod", "dev", "develop", "development", "qa", "stage", "staging", "release", "hotfix"];
35
+ };
36
+ /**
37
+ * Regex patterns for parsing git output
38
+ */
39
+ export declare const PATTERNS: {
40
+ /** Match commit SHA from porcelain output */
41
+ readonly COMMIT_SHA: RegExp;
42
+ /** Match worktree path from porcelain output */
43
+ readonly WORKTREE_PATH: RegExp;
44
+ /** Match branch from porcelain output */
45
+ readonly BRANCH_REF: RegExp;
46
+ };
47
+ /**
48
+ * Platform detection
49
+ */
50
+ export declare const PLATFORM: {
51
+ readonly IS_MAC: boolean;
52
+ readonly IS_WIN: boolean;
53
+ readonly IS_LINUX: boolean;
54
+ readonly IS_WSL: boolean;
55
+ };
56
+ /**
57
+ * Editor types and their display names
58
+ */
59
+ export declare const EDITORS: {
60
+ readonly code: {
61
+ readonly name: "VS Code";
62
+ readonly terminal: false;
63
+ };
64
+ readonly cursor: {
65
+ readonly name: "Cursor";
66
+ readonly terminal: false;
67
+ };
68
+ readonly zed: {
69
+ readonly name: "Zed";
70
+ readonly terminal: false;
71
+ };
72
+ readonly webstorm: {
73
+ readonly name: "WebStorm";
74
+ readonly terminal: false;
75
+ };
76
+ readonly subl: {
77
+ readonly name: "Sublime Text";
78
+ readonly terminal: false;
79
+ };
80
+ readonly nvim: {
81
+ readonly name: "Neovim";
82
+ readonly terminal: true;
83
+ };
84
+ };
85
+ /**
86
+ * AI tools and their display names
87
+ */
88
+ export declare const AI_TOOLS: {
89
+ readonly claude: {
90
+ readonly name: "Claude";
91
+ };
92
+ readonly gemini: {
93
+ readonly name: "Gemini";
94
+ };
95
+ readonly codex: {
96
+ readonly name: "Codex";
97
+ };
98
+ };
99
+ /**
100
+ * Installation instructions by platform
101
+ */
102
+ export declare const INSTALL_INSTRUCTIONS: {
103
+ readonly code: {
104
+ readonly darwin: "Open VS Code → Cmd+Shift+P → 'Shell Command: Install code'";
105
+ readonly win32: "Add VS Code to PATH during installation";
106
+ readonly linux: "Install via package manager or add to PATH";
107
+ };
108
+ readonly cursor: {
109
+ readonly darwin: "Open Cursor → Cmd+Shift+P → 'Shell Command: Install cursor'";
110
+ readonly win32: "Add Cursor to PATH during installation";
111
+ readonly linux: "Add Cursor to PATH";
112
+ };
113
+ readonly zed: {
114
+ readonly darwin: "Open Zed → Cmd+Shift+P → 'zed: Install CLI'";
115
+ readonly win32: "Zed CLI installation varies by setup";
116
+ readonly linux: "Zed CLI installation varies by setup";
117
+ };
118
+ readonly webstorm: {
119
+ readonly darwin: "Open WebStorm → Tools → Create Command-line Launcher";
120
+ readonly win32: "Add WebStorm to PATH";
121
+ readonly linux: "Add WebStorm to PATH";
122
+ };
123
+ readonly subl: {
124
+ readonly darwin: "See sublimetext.com/docs/command_line.html";
125
+ readonly win32: "See sublimetext.com/docs/command_line.html";
126
+ readonly linux: "See sublimetext.com/docs/command_line.html";
127
+ };
128
+ readonly nvim: {
129
+ readonly darwin: "Install via: brew install neovim";
130
+ readonly win32: "Install via: choco install neovim or scoop install neovim";
131
+ readonly linux: "Install via: apt install neovim or dnf install neovim";
132
+ };
133
+ readonly claude: {
134
+ readonly darwin: "Install Claude CLI: npm install -g @anthropic-ai/claude-code";
135
+ readonly win32: "Install Claude CLI: npm install -g @anthropic-ai/claude-code";
136
+ readonly linux: "Install Claude CLI: npm install -g @anthropic-ai/claude-code";
137
+ };
138
+ readonly gemini: {
139
+ readonly darwin: "Install Gemini CLI from Google";
140
+ readonly win32: "Install Gemini CLI from Google";
141
+ readonly linux: "Install Gemini CLI from Google";
142
+ };
143
+ readonly codex: {
144
+ readonly darwin: "Install Codex CLI from OpenAI";
145
+ readonly win32: "Install Codex CLI from OpenAI";
146
+ readonly linux: "Install Codex CLI from OpenAI";
147
+ };
148
+ };
149
+ /**
150
+ * Get install instruction for a tool on the current platform
151
+ */
152
+ export declare function getInstallInstruction(tool: string): string;
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Constants used throughout the worktree manager application
3
+ */
4
+ /**
5
+ * UI-related constants
6
+ */
7
+ export const UI = {
8
+ /** Maximum length for branch names in list display */
9
+ BRANCH_TRUNCATE_LENGTH: 30,
10
+ /** Height of the help modal in lines */
11
+ HELP_MODAL_HEIGHT: 26,
12
+ /** Height of the create worktree form in lines */
13
+ CREATE_FORM_HEIGHT: 20,
14
+ /** Width of modal dialogs */
15
+ MODAL_WIDTH: 50,
16
+ /** Width of the editor/AI selection dialog */
17
+ SELECTOR_WIDTH: 40,
18
+ /** Height of the editor selection dialog */
19
+ EDITOR_SELECTOR_HEIGHT: 12,
20
+ /** Height of the AI tool selection dialog */
21
+ AI_SELECTOR_HEIGHT: 9,
22
+ };
23
+ /**
24
+ * Git-related constants
25
+ */
26
+ export const GIT = {
27
+ /** Length of short SHA commit hash */
28
+ SHORT_SHA_LENGTH: 7,
29
+ /** Default base branch name */
30
+ DEFAULT_BASE_BRANCH: 'main',
31
+ /** Directory name for worktrees relative to repo */
32
+ WORKTREES_DIR: 'worktrees',
33
+ /** Branches that should never be offered for deletion */
34
+ PROTECTED_BRANCHES: [
35
+ 'main',
36
+ 'master',
37
+ 'production',
38
+ 'prod',
39
+ 'dev',
40
+ 'develop',
41
+ 'development',
42
+ 'qa',
43
+ 'stage',
44
+ 'staging',
45
+ 'release',
46
+ 'hotfix',
47
+ ],
48
+ };
49
+ /**
50
+ * Regex patterns for parsing git output
51
+ */
52
+ export const PATTERNS = {
53
+ /** Match commit SHA from porcelain output */
54
+ COMMIT_SHA: /^HEAD ([a-f0-9]+)$/,
55
+ /** Match worktree path from porcelain output */
56
+ WORKTREE_PATH: /^worktree (.+)$/,
57
+ /** Match branch from porcelain output */
58
+ BRANCH_REF: /^branch refs\/heads\/(.+)$/,
59
+ };
60
+ /**
61
+ * Platform detection
62
+ */
63
+ export const PLATFORM = {
64
+ IS_MAC: process.platform === 'darwin',
65
+ IS_WIN: process.platform === 'win32',
66
+ IS_LINUX: process.platform === 'linux',
67
+ IS_WSL: process.platform === 'linux' && !!process.env.WSL_DISTRO_NAME,
68
+ };
69
+ /**
70
+ * Editor types and their display names
71
+ */
72
+ export const EDITORS = {
73
+ code: { name: 'VS Code', terminal: false },
74
+ cursor: { name: 'Cursor', terminal: false },
75
+ zed: { name: 'Zed', terminal: false },
76
+ webstorm: { name: 'WebStorm', terminal: false },
77
+ subl: { name: 'Sublime Text', terminal: false },
78
+ nvim: { name: 'Neovim', terminal: true },
79
+ };
80
+ /**
81
+ * AI tools and their display names
82
+ */
83
+ export const AI_TOOLS = {
84
+ claude: { name: 'Claude' },
85
+ gemini: { name: 'Gemini' },
86
+ codex: { name: 'Codex' },
87
+ };
88
+ /**
89
+ * Installation instructions by platform
90
+ */
91
+ export const INSTALL_INSTRUCTIONS = {
92
+ code: {
93
+ darwin: "Open VS Code → Cmd+Shift+P → 'Shell Command: Install code'",
94
+ win32: 'Add VS Code to PATH during installation',
95
+ linux: 'Install via package manager or add to PATH',
96
+ },
97
+ cursor: {
98
+ darwin: "Open Cursor → Cmd+Shift+P → 'Shell Command: Install cursor'",
99
+ win32: 'Add Cursor to PATH during installation',
100
+ linux: 'Add Cursor to PATH',
101
+ },
102
+ zed: {
103
+ darwin: "Open Zed → Cmd+Shift+P → 'zed: Install CLI'",
104
+ win32: 'Zed CLI installation varies by setup',
105
+ linux: 'Zed CLI installation varies by setup',
106
+ },
107
+ webstorm: {
108
+ darwin: 'Open WebStorm → Tools → Create Command-line Launcher',
109
+ win32: 'Add WebStorm to PATH',
110
+ linux: 'Add WebStorm to PATH',
111
+ },
112
+ subl: {
113
+ darwin: 'See sublimetext.com/docs/command_line.html',
114
+ win32: 'See sublimetext.com/docs/command_line.html',
115
+ linux: 'See sublimetext.com/docs/command_line.html',
116
+ },
117
+ nvim: {
118
+ darwin: 'Install via: brew install neovim',
119
+ win32: 'Install via: choco install neovim or scoop install neovim',
120
+ linux: 'Install via: apt install neovim or dnf install neovim',
121
+ },
122
+ claude: {
123
+ darwin: 'Install Claude CLI: npm install -g @anthropic-ai/claude-code',
124
+ win32: 'Install Claude CLI: npm install -g @anthropic-ai/claude-code',
125
+ linux: 'Install Claude CLI: npm install -g @anthropic-ai/claude-code',
126
+ },
127
+ gemini: {
128
+ darwin: 'Install Gemini CLI from Google',
129
+ win32: 'Install Gemini CLI from Google',
130
+ linux: 'Install Gemini CLI from Google',
131
+ },
132
+ codex: {
133
+ darwin: 'Install Codex CLI from OpenAI',
134
+ win32: 'Install Codex CLI from OpenAI',
135
+ linux: 'Install Codex CLI from OpenAI',
136
+ },
137
+ };
138
+ /**
139
+ * Get install instruction for a tool on the current platform
140
+ */
141
+ export function getInstallInstruction(tool) {
142
+ const instructions = INSTALL_INSTRUCTIONS[tool];
143
+ if (!instructions) {
144
+ return `Install ${tool}`;
145
+ }
146
+ const platform = process.platform;
147
+ return instructions[platform] || instructions.darwin || `Install ${tool}`;
148
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Custom error classes for better error handling and debugging
3
+ */
4
+ /**
5
+ * Base error class for all worktree manager errors
6
+ */
7
+ export declare class WorktreeManagerError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ /**
11
+ * Error thrown when a git command fails
12
+ */
13
+ export declare class GitCommandError extends WorktreeManagerError {
14
+ readonly command: string;
15
+ readonly stderr: string;
16
+ readonly exitCode: number | undefined;
17
+ constructor(message: string, command: string, stderr?: string, exitCode?: number);
18
+ /**
19
+ * Get a user-friendly error message
20
+ */
21
+ getUserMessage(): string;
22
+ }
23
+ /**
24
+ * Error thrown when a worktree is not found
25
+ */
26
+ export declare class WorktreeNotFoundError extends WorktreeManagerError {
27
+ readonly worktreePath: string;
28
+ constructor(worktreePath: string);
29
+ }
30
+ /**
31
+ * Error thrown when a branch name is invalid
32
+ */
33
+ export declare class InvalidBranchError extends WorktreeManagerError {
34
+ readonly branch: string;
35
+ readonly reason: string;
36
+ constructor(branch: string, reason?: string);
37
+ }
38
+ /**
39
+ * Error thrown when a path is invalid or contains traversal attempts
40
+ */
41
+ export declare class InvalidPathError extends WorktreeManagerError {
42
+ readonly invalidPath: string;
43
+ readonly reason: string;
44
+ constructor(invalidPath: string, reason?: string);
45
+ }
46
+ /**
47
+ * Error thrown when an external tool (editor, terminal, AI) is not found
48
+ */
49
+ export declare class ToolNotFoundError extends WorktreeManagerError {
50
+ readonly toolName: string;
51
+ readonly installHint: string;
52
+ constructor(toolName: string, installHint?: string);
53
+ }
54
+ /**
55
+ * Parse an error from git command execution into a GitCommandError
56
+ */
57
+ export declare function parseGitError(error: unknown, command: string): GitCommandError;
package/dist/errors.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Custom error classes for better error handling and debugging
3
+ */
4
+ /**
5
+ * Base error class for all worktree manager errors
6
+ */
7
+ export class WorktreeManagerError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'WorktreeManagerError';
11
+ // Maintains proper stack trace for where error was thrown (V8 engines)
12
+ if (Error.captureStackTrace) {
13
+ Error.captureStackTrace(this, this.constructor);
14
+ }
15
+ }
16
+ }
17
+ /**
18
+ * Error thrown when a git command fails
19
+ */
20
+ export class GitCommandError extends WorktreeManagerError {
21
+ command;
22
+ stderr;
23
+ exitCode;
24
+ constructor(message, command, stderr = '', exitCode) {
25
+ super(message);
26
+ this.name = 'GitCommandError';
27
+ this.command = command;
28
+ this.stderr = stderr;
29
+ this.exitCode = exitCode;
30
+ }
31
+ /**
32
+ * Get a user-friendly error message
33
+ */
34
+ getUserMessage() {
35
+ // Parse common git errors into friendly messages
36
+ if (this.stderr.includes('not a git repository')) {
37
+ return 'This directory is not a git repository';
38
+ }
39
+ if (this.stderr.includes('already exists')) {
40
+ return 'A worktree or branch with this name already exists';
41
+ }
42
+ if (this.stderr.includes('is not a valid branch name')) {
43
+ return 'Invalid branch name. Branch names cannot contain spaces or special characters';
44
+ }
45
+ if (this.stderr.includes('invalid reference')) {
46
+ return 'The specified branch or commit does not exist';
47
+ }
48
+ if (this.stderr.includes('contains modified or untracked files')) {
49
+ return 'Worktree has uncommitted changes. Use force to delete anyway';
50
+ }
51
+ // Return original message if no specific parsing applies
52
+ return this.message;
53
+ }
54
+ }
55
+ /**
56
+ * Error thrown when a worktree is not found
57
+ */
58
+ export class WorktreeNotFoundError extends WorktreeManagerError {
59
+ worktreePath;
60
+ constructor(worktreePath) {
61
+ super(`Worktree not found: ${worktreePath}`);
62
+ this.name = 'WorktreeNotFoundError';
63
+ this.worktreePath = worktreePath;
64
+ }
65
+ }
66
+ /**
67
+ * Error thrown when a branch name is invalid
68
+ */
69
+ export class InvalidBranchError extends WorktreeManagerError {
70
+ branch;
71
+ reason;
72
+ constructor(branch, reason = 'Invalid branch name') {
73
+ super(`Invalid branch name "${branch}": ${reason}`);
74
+ this.name = 'InvalidBranchError';
75
+ this.branch = branch;
76
+ this.reason = reason;
77
+ }
78
+ }
79
+ /**
80
+ * Error thrown when a path is invalid or contains traversal attempts
81
+ */
82
+ export class InvalidPathError extends WorktreeManagerError {
83
+ invalidPath;
84
+ reason;
85
+ constructor(invalidPath, reason = 'Invalid path') {
86
+ super(`Invalid path "${invalidPath}": ${reason}`);
87
+ this.name = 'InvalidPathError';
88
+ this.invalidPath = invalidPath;
89
+ this.reason = reason;
90
+ }
91
+ }
92
+ /**
93
+ * Error thrown when an external tool (editor, terminal, AI) is not found
94
+ */
95
+ export class ToolNotFoundError extends WorktreeManagerError {
96
+ toolName;
97
+ installHint;
98
+ constructor(toolName, installHint = '') {
99
+ super(`${toolName} not found${installHint ? `. ${installHint}` : ''}`);
100
+ this.name = 'ToolNotFoundError';
101
+ this.toolName = toolName;
102
+ this.installHint = installHint;
103
+ }
104
+ }
105
+ /**
106
+ * Parse an error from git command execution into a GitCommandError
107
+ */
108
+ export function parseGitError(error, command) {
109
+ if (error instanceof GitCommandError) {
110
+ return error;
111
+ }
112
+ const err = error;
113
+ const message = err.message || String(error);
114
+ const stderr = err.stderr || '';
115
+ const exitCode = typeof err.code === 'number' ? err.code : undefined;
116
+ return new GitCommandError(message, command, stderr, exitCode);
117
+ }