ccmanager 3.5.0 → 3.5.2

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 (82) hide show
  1. package/dist/cli.js +3 -2
  2. package/dist/components/App.d.ts +1 -0
  3. package/dist/components/App.js +17 -39
  4. package/dist/components/App.test.js +12 -44
  5. package/dist/components/Configuration.js +10 -15
  6. package/dist/components/ConfigureCommand.js +18 -106
  7. package/dist/components/ConfigureCustomCommand.js +2 -17
  8. package/dist/components/ConfigureOther.js +5 -23
  9. package/dist/components/ConfigureOther.test.js +7 -31
  10. package/dist/components/ConfigureShortcuts.js +4 -31
  11. package/dist/components/ConfigureStatusHooks.js +5 -44
  12. package/dist/components/ConfigureStatusHooks.test.js +7 -31
  13. package/dist/components/ConfigureTimeout.js +2 -14
  14. package/dist/components/ConfigureWorktree.js +4 -47
  15. package/dist/components/ConfigureWorktreeHooks.js +5 -37
  16. package/dist/components/ConfigureWorktreeHooks.test.js +8 -33
  17. package/dist/components/Confirmation.js +9 -21
  18. package/dist/components/CustomCommandSummary.js +2 -5
  19. package/dist/components/DeleteConfirmation.js +10 -47
  20. package/dist/components/DeleteWorktree.js +14 -42
  21. package/dist/components/DeleteWorktree.test.js +6 -6
  22. package/dist/components/LoadingSpinner.js +3 -6
  23. package/dist/components/LoadingSpinner.test.js +22 -22
  24. package/dist/components/Menu.d.ts +1 -0
  25. package/dist/components/Menu.js +10 -42
  26. package/dist/components/Menu.recent-projects.test.js +8 -8
  27. package/dist/components/Menu.test.js +10 -10
  28. package/dist/components/MergeWorktree.js +16 -88
  29. package/dist/components/MergeWorktree.test.js +5 -5
  30. package/dist/components/NewWorktree.js +25 -105
  31. package/dist/components/NewWorktree.test.js +8 -8
  32. package/dist/components/PresetSelector.js +3 -9
  33. package/dist/components/ProjectList.js +9 -38
  34. package/dist/components/ProjectList.recent-projects.test.js +7 -7
  35. package/dist/components/ProjectList.test.js +37 -37
  36. package/dist/components/RemoteBranchSelector.js +2 -21
  37. package/dist/components/RemoteBranchSelector.test.js +8 -8
  38. package/dist/components/TextInputWrapper.d.ts +5 -0
  39. package/dist/components/TextInputWrapper.js +138 -11
  40. package/dist/constants/statusIcons.d.ts +2 -1
  41. package/dist/constants/statusIcons.js +13 -4
  42. package/dist/constants/statusIcons.test.js +41 -11
  43. package/dist/contexts/ConfigEditorContext.d.ts +1 -1
  44. package/dist/contexts/ConfigEditorContext.js +3 -2
  45. package/dist/services/autoApprovalVerifier.js +1 -8
  46. package/dist/services/bunTerminal.js +41 -136
  47. package/dist/services/config/configEditor.js +2 -12
  48. package/dist/services/config/globalConfigManager.js +4 -24
  49. package/dist/services/config/projectConfigManager.js +3 -18
  50. package/dist/services/globalSessionOrchestrator.js +3 -12
  51. package/dist/services/globalSessionOrchestrator.test.js +1 -8
  52. package/dist/services/projectManager.js +13 -68
  53. package/dist/services/sessionManager.d.ts +1 -1
  54. package/dist/services/sessionManager.effect.test.js +9 -37
  55. package/dist/services/sessionManager.js +12 -28
  56. package/dist/services/sessionManager.test.js +48 -40
  57. package/dist/services/shortcutManager.js +7 -13
  58. package/dist/services/stateDetector/base.d.ts +1 -1
  59. package/dist/services/stateDetector/claude.d.ts +1 -1
  60. package/dist/services/stateDetector/claude.js +11 -4
  61. package/dist/services/stateDetector/claude.test.js +47 -24
  62. package/dist/services/stateDetector/cline.d.ts +1 -1
  63. package/dist/services/stateDetector/cline.js +1 -1
  64. package/dist/services/stateDetector/codex.d.ts +1 -1
  65. package/dist/services/stateDetector/codex.js +1 -1
  66. package/dist/services/stateDetector/cursor.d.ts +1 -1
  67. package/dist/services/stateDetector/cursor.js +1 -1
  68. package/dist/services/stateDetector/gemini.d.ts +1 -1
  69. package/dist/services/stateDetector/gemini.js +1 -1
  70. package/dist/services/stateDetector/github-copilot.d.ts +1 -1
  71. package/dist/services/stateDetector/github-copilot.js +1 -1
  72. package/dist/services/stateDetector/opencode.d.ts +1 -1
  73. package/dist/services/stateDetector/opencode.js +1 -1
  74. package/dist/services/stateDetector/types.d.ts +1 -1
  75. package/dist/services/worktreeConfigManager.js +3 -8
  76. package/dist/services/worktreeService.js +2 -12
  77. package/dist/types/index.js +4 -12
  78. package/dist/utils/logger.js +12 -33
  79. package/dist/utils/mutex.d.ts +1 -1
  80. package/dist/utils/mutex.js +4 -19
  81. package/dist/utils/worktreeUtils.js +4 -4
  82. package/package.json +12 -12
@@ -1,4 +1,5 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
2
3
  import { Box, Text, useInput } from 'ink';
3
4
  import SelectInput from 'ink-select-input';
4
5
  import { Effect } from 'effect';
@@ -99,116 +100,43 @@ const MergeWorktree = ({ onComplete, onCancel, }) => {
99
100
  performMerge();
100
101
  }, [step, sourceBranch, targetBranch, useRebase, worktreeService]);
101
102
  if (isLoading) {
102
- return (React.createElement(Box, { flexDirection: "column" },
103
- React.createElement(Text, { color: "cyan" }, "Loading worktrees...")));
103
+ return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { color: "cyan", children: "Loading worktrees..." }) }));
104
104
  }
105
105
  if (loadError) {
106
- return (React.createElement(Box, { flexDirection: "column" },
107
- React.createElement(Text, { color: "red" }, "Error loading worktrees:"),
108
- React.createElement(Text, { color: "red" }, loadError),
109
- React.createElement(Box, { marginTop: 1 },
110
- React.createElement(Text, { dimColor: true },
111
- "Press ",
112
- shortcutManager.getShortcutDisplay('cancel'),
113
- " to return to menu"))));
106
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "Error loading worktrees:" }), _jsx(Text, { color: "red", children: loadError }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to return to menu"] }) })] }));
114
107
  }
115
108
  if (step === 'select-source') {
116
- return (React.createElement(Box, { flexDirection: "column" },
117
- React.createElement(Box, { marginBottom: 1 },
118
- React.createElement(Text, { bold: true, color: "green" }, "Merge Worktree")),
119
- React.createElement(Box, { marginBottom: 1 },
120
- React.createElement(Text, null, "Select the source branch to merge:")),
121
- React.createElement(SelectInput, { items: branchItems, onSelect: handleSelectSource, isFocused: true, limit: 10 }),
122
- React.createElement(Box, { marginTop: 1 },
123
- React.createElement(Text, { dimColor: true },
124
- "Press ",
125
- shortcutManager.getShortcutDisplay('cancel'),
126
- " to cancel"))));
109
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Merge Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select the source branch to merge:" }) }), _jsx(SelectInput, { items: branchItems, onSelect: handleSelectSource, isFocused: true, limit: 10 }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
127
110
  }
128
111
  if (step === 'select-target') {
129
- return (React.createElement(Box, { flexDirection: "column" },
130
- React.createElement(Box, { marginBottom: 1 },
131
- React.createElement(Text, { bold: true, color: "green" }, "Merge Worktree")),
132
- React.createElement(Box, { marginBottom: 1 },
133
- React.createElement(Text, null,
134
- "Merging from: ",
135
- React.createElement(Text, { color: "yellow" }, sourceBranch))),
136
- React.createElement(Box, { marginBottom: 1 },
137
- React.createElement(Text, null, "Select the target branch to merge into:")),
138
- React.createElement(SelectInput, { items: branchItems, onSelect: handleSelectTarget, isFocused: true, limit: 10 }),
139
- React.createElement(Box, { marginTop: 1 },
140
- React.createElement(Text, { dimColor: true },
141
- "Press ",
142
- shortcutManager.getShortcutDisplay('cancel'),
143
- " to cancel"))));
112
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Merge Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Merging from: ", _jsx(Text, { color: "yellow", children: sourceBranch })] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select the target branch to merge into:" }) }), _jsx(SelectInput, { items: branchItems, onSelect: handleSelectTarget, isFocused: true, limit: 10 }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
144
113
  }
145
114
  if (step === 'select-operation') {
146
- const title = (React.createElement(Text, { bold: true, color: "green" }, "Select Operation"));
147
- const message = (React.createElement(Text, null,
148
- "Choose how to integrate ",
149
- React.createElement(Text, { color: "yellow" }, sourceBranch),
150
- " into",
151
- ' ',
152
- React.createElement(Text, { color: "yellow" }, targetBranch),
153
- ":"));
154
- const hint = (React.createElement(Text, { dimColor: true },
155
- "Use \u2191\u2193/j/k to navigate, Enter to select,",
156
- ' ',
157
- shortcutManager.getShortcutDisplay('cancel'),
158
- " to cancel"));
115
+ const title = (_jsx(Text, { bold: true, color: "green", children: "Select Operation" }));
116
+ const message = (_jsxs(Text, { children: ["Choose how to integrate ", _jsx(Text, { color: "yellow", children: sourceBranch }), " into", ' ', _jsx(Text, { color: "yellow", children: targetBranch }), ":"] }));
117
+ const hint = (_jsxs(Text, { dimColor: true, children: ["Use \u2191\u2193/j/k to navigate, Enter to select,", ' ', shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }));
159
118
  const handleOperationSelect = (value) => {
160
119
  setUseRebase(value === 'rebase');
161
120
  setStep('confirm-merge');
162
121
  };
163
- return (React.createElement(Confirmation, { title: title, message: message, options: [
122
+ return (_jsx(Confirmation, { title: title, message: message, options: [
164
123
  { label: 'Merge', value: 'merge', color: 'green' },
165
124
  { label: 'Rebase', value: 'rebase', color: 'blue' },
166
125
  ], onSelect: handleOperationSelect, initialIndex: 0, hint: hint }));
167
126
  }
168
127
  if (step === 'confirm-merge') {
169
- const confirmMessage = (React.createElement(Box, { flexDirection: "column" },
170
- React.createElement(Box, { marginBottom: 1 },
171
- React.createElement(Text, { bold: true, color: "green" },
172
- "Confirm ",
173
- useRebase ? 'Rebase' : 'Merge')),
174
- React.createElement(Text, null,
175
- useRebase ? 'Rebase' : 'Merge',
176
- ' ',
177
- React.createElement(Text, { color: "yellow" }, sourceBranch),
178
- ' ',
179
- useRebase ? 'onto' : 'into',
180
- ' ',
181
- React.createElement(Text, { color: "yellow" }, targetBranch),
182
- "?")));
183
- return (React.createElement(SimpleConfirmation, { message: confirmMessage, onConfirm: () => setStep('executing-merge'), onCancel: onCancel }));
128
+ const confirmMessage = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "green", children: ["Confirm ", useRebase ? 'Rebase' : 'Merge'] }) }), _jsxs(Text, { children: [useRebase ? 'Rebase' : 'Merge', ' ', _jsx(Text, { color: "yellow", children: sourceBranch }), ' ', useRebase ? 'onto' : 'into', ' ', _jsx(Text, { color: "yellow", children: targetBranch }), "?"] })] }));
129
+ return (_jsx(SimpleConfirmation, { message: confirmMessage, onConfirm: () => setStep('executing-merge'), onCancel: onCancel }));
184
130
  }
185
131
  if (step === 'executing-merge') {
186
- return (React.createElement(Box, { flexDirection: "column" },
187
- React.createElement(Text, { color: "green" },
188
- useRebase ? 'Rebasing' : 'Merging',
189
- " branches...")));
132
+ return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "green", children: [useRebase ? 'Rebasing' : 'Merging', " branches..."] }) }));
190
133
  }
191
134
  if (step === 'merge-error') {
192
- return (React.createElement(Box, { flexDirection: "column" },
193
- React.createElement(Box, { marginBottom: 1 },
194
- React.createElement(Text, { bold: true, color: "red" },
195
- useRebase ? 'Rebase' : 'Merge',
196
- " Failed")),
197
- React.createElement(Box, { marginBottom: 1 },
198
- React.createElement(Text, { color: "red" }, mergeError)),
199
- React.createElement(Box, { marginTop: 1 },
200
- React.createElement(Text, { dimColor: true }, "Press any key to return to menu"))));
135
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: "red", children: [useRebase ? 'Rebase' : 'Merge', " Failed"] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: mergeError }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press any key to return to menu" }) })] }));
201
136
  }
202
137
  if (step === 'delete-confirm') {
203
- const deleteMessage = (React.createElement(Box, { flexDirection: "column" },
204
- React.createElement(Box, { marginBottom: 1 },
205
- React.createElement(Text, { bold: true, color: "green" }, "Delete Source Branch?")),
206
- React.createElement(Text, null,
207
- "Delete the merged branch ",
208
- React.createElement(Text, { color: "yellow" }, sourceBranch),
209
- ' ',
210
- "and its worktree?")));
211
- return (React.createElement(SimpleConfirmation, { message: deleteMessage, onConfirm: async () => {
138
+ const deleteMessage = (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Delete Source Branch?" }) }), _jsxs(Text, { children: ["Delete the merged branch ", _jsx(Text, { color: "yellow", children: sourceBranch }), ' ', "and its worktree?"] })] }));
139
+ return (_jsx(SimpleConfirmation, { message: deleteMessage, onConfirm: async () => {
212
140
  try {
213
141
  // Find the worktree path for the source branch
214
142
  const worktrees = await Effect.runPromise(worktreeService.getWorktreesEffect());
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { render } from 'ink-testing-library';
3
3
  import { describe, it, expect, vi, beforeEach } from 'vitest';
4
4
  import { Effect } from 'effect';
@@ -66,7 +66,7 @@ describe('MergeWorktree - Effect Integration', () => {
66
66
  const onComplete = vi.fn();
67
67
  const onCancel = vi.fn();
68
68
  // WHEN: Component is rendered
69
- const { lastFrame } = render(React.createElement(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
69
+ const { lastFrame } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
70
70
  // Wait for Effect to execute
71
71
  await new Promise(resolve => setTimeout(resolve, 50));
72
72
  // THEN: Effect method should be called
@@ -105,7 +105,7 @@ describe('MergeWorktree - Effect Integration', () => {
105
105
  const onComplete = vi.fn();
106
106
  const onCancel = vi.fn();
107
107
  // WHEN: Component renders and user selects branches
108
- const { stdin } = render(React.createElement(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
108
+ const { stdin } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
109
109
  // Wait for initial load
110
110
  await new Promise(resolve => setTimeout(resolve, 50));
111
111
  // Simulate selecting source branch (Enter key)
@@ -162,7 +162,7 @@ describe('MergeWorktree - Effect Integration', () => {
162
162
  const onComplete = vi.fn();
163
163
  const onCancel = vi.fn();
164
164
  // WHEN: Component renders and attempts merge
165
- const { stdin, lastFrame } = render(React.createElement(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
165
+ const { stdin, lastFrame } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
166
166
  // Wait for initial load
167
167
  await new Promise(resolve => setTimeout(resolve, 50));
168
168
  // Go through merge flow
@@ -216,7 +216,7 @@ describe('MergeWorktree - Effect Integration', () => {
216
216
  const onComplete = vi.fn();
217
217
  const onCancel = vi.fn();
218
218
  // WHEN: Component renders and completes merge with delete
219
- const { stdin } = render(React.createElement(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
219
+ const { stdin } = render(_jsx(MergeWorktree, { onComplete: onComplete, onCancel: onCancel }));
220
220
  await new Promise(resolve => setTimeout(resolve, 50));
221
221
  stdin.write('\r'); // Select source
222
222
  await new Promise(resolve => setTimeout(resolve, 50));
@@ -1,4 +1,5 @@
1
- import React, { useState, useMemo, useEffect } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useMemo, useEffect } from 'react';
2
3
  import { Box, Text, useInput } from 'ink';
3
4
  import TextInputWrapper from './TextInputWrapper.js';
4
5
  import SelectInput from 'ink-select-input';
@@ -164,113 +165,32 @@ const NewWorktree = ({ projectPath, onComplete, onCancel, }) => {
164
165
  };
165
166
  // Show loading indicator while branches load
166
167
  if (isLoadingBranches) {
167
- return (React.createElement(Box, { flexDirection: "column" },
168
- React.createElement(Box, { marginBottom: 1 },
169
- React.createElement(Text, { bold: true, color: "green" }, "Create New Worktree")),
170
- React.createElement(Box, null,
171
- React.createElement(Text, null, "Loading branches...")),
172
- React.createElement(Box, { marginTop: 1 },
173
- React.createElement(Text, { dimColor: true },
174
- "Press ",
175
- shortcutManager.getShortcutDisplay('cancel'),
176
- " to cancel"))));
168
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), _jsx(Box, { children: _jsx(Text, { children: "Loading branches..." }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
177
169
  }
178
170
  // Show error message if branch loading failed
179
171
  if (branchLoadError) {
180
- return (React.createElement(Box, { flexDirection: "column" },
181
- React.createElement(Box, { marginBottom: 1 },
182
- React.createElement(Text, { bold: true, color: "green" }, "Create New Worktree")),
183
- React.createElement(Box, { marginBottom: 1 },
184
- React.createElement(Text, { color: "red" }, "Error loading branches:")),
185
- React.createElement(Box, { marginBottom: 1 },
186
- React.createElement(Text, { color: "red" }, branchLoadError)),
187
- React.createElement(Box, { marginTop: 1 },
188
- React.createElement(Text, { dimColor: true },
189
- "Press ",
190
- shortcutManager.getShortcutDisplay('cancel'),
191
- " to go back"))));
172
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: "Error loading branches:" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: branchLoadError }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to go back"] }) })] }));
192
173
  }
193
- return (React.createElement(Box, { flexDirection: "column" },
194
- React.createElement(Box, { marginBottom: 1 },
195
- React.createElement(Text, { bold: true, color: "green" }, "Create New Worktree")),
196
- step === 'path' && !isAutoDirectory ? (React.createElement(Box, { flexDirection: "column" },
197
- React.createElement(Box, { marginBottom: 1 },
198
- React.createElement(Text, null, "Enter worktree path (relative to repository root):")),
199
- React.createElement(Box, null,
200
- React.createElement(Text, { color: "cyan" }, '> '),
201
- React.createElement(TextInputWrapper, { value: path, onChange: setPath, onSubmit: handlePathSubmit, placeholder: "e.g., ../myproject-feature" })))) : null,
202
- step === 'base-branch' && (React.createElement(Box, { flexDirection: "column" },
203
- React.createElement(Box, { marginBottom: 1 },
204
- React.createElement(Text, null, "Select base branch for the worktree:")),
205
- isSearchMode && (React.createElement(Box, { marginBottom: 1 },
206
- React.createElement(Text, null, "Search: "),
207
- React.createElement(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter branches..." }))),
208
- isSearchMode && branchItems.length === 0 ? (React.createElement(Box, null,
209
- React.createElement(Text, { color: "yellow" }, "No branches match your search"))) : isSearchMode ? (
210
- // In search mode, show the items as a list without SelectInput
211
- React.createElement(Box, { flexDirection: "column" }, branchItems.slice(0, limit).map((item, index) => (React.createElement(Text, { key: item.value, color: index === selectedIndex ? 'green' : undefined },
212
- index === selectedIndex ? '❯ ' : ' ',
213
- item.label))))) : (React.createElement(SelectInput, { items: branchItems, onSelect: handleBaseBranchSelect, initialIndex: selectedIndex, limit: limit, isFocused: !isSearchMode })),
214
- !isSearchMode && (React.createElement(Box, { marginTop: 1 },
215
- React.createElement(Text, { dimColor: true }, "Press / to search"))))),
216
- step === 'branch-strategy' && (React.createElement(Box, { flexDirection: "column" },
217
- React.createElement(Box, { marginBottom: 1 },
218
- React.createElement(Text, null,
219
- "Base branch: ",
220
- React.createElement(Text, { color: "cyan" }, baseBranch))),
221
- React.createElement(Box, { marginBottom: 1 },
222
- React.createElement(Text, null, "Choose branch creation strategy:")),
223
- React.createElement(SelectInput, { items: [
224
- {
225
- label: 'Create new branch from base branch',
226
- value: 'new',
227
- },
228
- {
229
- label: 'Use existing base branch',
230
- value: 'existing',
231
- },
232
- ], onSelect: handleBranchStrategySelect, initialIndex: 0 }))),
233
- step === 'branch' && (React.createElement(Box, { flexDirection: "column" },
234
- React.createElement(Box, { marginBottom: 1 },
235
- React.createElement(Text, null,
236
- "Enter new branch name (will be created from",
237
- ' ',
238
- React.createElement(Text, { color: "cyan" }, baseBranch),
239
- "):")),
240
- React.createElement(Box, null,
241
- React.createElement(Text, { color: "cyan" }, '> '),
242
- React.createElement(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })),
243
- isAutoDirectory && generatedPath && (React.createElement(Box, { marginTop: 1 },
244
- React.createElement(Text, { dimColor: true },
245
- "Worktree will be created at:",
246
- ' ',
247
- React.createElement(Text, { color: "green" }, generatedPath)))))),
248
- step === 'copy-settings' && (React.createElement(Box, { flexDirection: "column" },
249
- React.createElement(Box, { marginBottom: 1 },
250
- React.createElement(Text, null,
251
- "Copy .claude directory from base branch (",
252
- React.createElement(Text, { color: "cyan" }, baseBranch),
253
- ")?")),
254
- React.createElement(SelectInput, { items: [
255
- {
256
- label: 'Yes - Copy .claude directory from base branch',
257
- value: true,
258
- },
259
- { label: 'No - Start without .claude directory', value: false },
260
- ], onSelect: handleCopySettingsSelect, initialIndex: 0 }))),
261
- step === 'copy-session' && (React.createElement(Box, { flexDirection: "column" },
262
- React.createElement(Box, { marginBottom: 1 },
263
- React.createElement(Text, null, "Copy Claude Code session data to the new worktree?")),
264
- React.createElement(Box, { marginBottom: 1 },
265
- React.createElement(Text, { dimColor: true }, "This will copy conversation history and context from the current worktree")),
266
- React.createElement(SelectInput, { items: [
267
- { label: '✅ Yes, copy session data', value: 'yes' },
268
- { label: '❌ No, start fresh', value: 'no' },
269
- ], onSelect: handleCopySessionSelect, initialIndex: copySessionData ? 0 : 1 }))),
270
- React.createElement(Box, { marginTop: 1 },
271
- React.createElement(Text, { dimColor: true },
272
- "Press ",
273
- shortcutManager.getShortcutDisplay('cancel'),
274
- " to cancel"))));
174
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Create New Worktree" }) }), step === 'path' && !isAutoDirectory ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Enter worktree path (relative to repository root):" }) }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '> ' }), _jsx(TextInputWrapper, { value: path, onChange: setPath, onSubmit: handlePathSubmit, placeholder: "e.g., ../myproject-feature" })] })] })) : null, step === 'base-branch' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Select base branch for the worktree:" }) }), isSearchMode && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { children: "Search: " }), _jsx(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter branches..." })] })), isSearchMode && branchItems.length === 0 ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No branches match your search" }) })) : isSearchMode ? (
175
+ // In search mode, show the items as a list without SelectInput
176
+ _jsx(Box, { flexDirection: "column", children: branchItems.slice(0, limit).map((item, index) => (_jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', item.label] }, item.value))) })) : (_jsx(SelectInput, { items: branchItems, onSelect: handleBaseBranchSelect, initialIndex: selectedIndex, limit: limit, isFocused: !isSearchMode })), !isSearchMode && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press / to search" }) }))] })), step === 'branch-strategy' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Base branch: ", _jsx(Text, { color: "cyan", children: baseBranch })] }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Choose branch creation strategy:" }) }), _jsx(SelectInput, { items: [
177
+ {
178
+ label: 'Create new branch from base branch',
179
+ value: 'new',
180
+ },
181
+ {
182
+ label: 'Use existing base branch',
183
+ value: 'existing',
184
+ },
185
+ ], onSelect: handleBranchStrategySelect, initialIndex: 0 })] })), step === 'branch' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Enter new branch name (will be created from", ' ', _jsx(Text, { color: "cyan", children: baseBranch }), "):"] }) }), _jsxs(Box, { children: [_jsx(Text, { color: "cyan", children: '> ' }), _jsx(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })] }), isAutoDirectory && generatedPath && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Worktree will be created at:", ' ', _jsx(Text, { color: "green", children: generatedPath })] }) }))] })), step === 'copy-settings' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { children: ["Copy .claude directory from base branch (", _jsx(Text, { color: "cyan", children: baseBranch }), ")?"] }) }), _jsx(SelectInput, { items: [
186
+ {
187
+ label: 'Yes - Copy .claude directory from base branch',
188
+ value: true,
189
+ },
190
+ { label: 'No - Start without .claude directory', value: false },
191
+ ], onSelect: handleCopySettingsSelect, initialIndex: 0 })] })), step === 'copy-session' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: "Copy Claude Code session data to the new worktree?" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "This will copy conversation history and context from the current worktree" }) }), _jsx(SelectInput, { items: [
192
+ { label: '✅ Yes, copy session data', value: 'yes' },
193
+ { label: '❌ No, start fresh', value: 'no' },
194
+ ], onSelect: handleCopySessionSelect, initialIndex: copySessionData ? 0 : 1 })] })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Press ", shortcutManager.getShortcutDisplay('cancel'), " to cancel"] }) })] }));
275
195
  };
276
196
  export default NewWorktree;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { render } from 'ink-testing-library';
3
3
  import NewWorktree from './NewWorktree.js';
4
4
  import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
@@ -89,7 +89,7 @@ describe('NewWorktree component Effect integration', () => {
89
89
  });
90
90
  const onComplete = vi.fn();
91
91
  const onCancel = vi.fn();
92
- const { lastFrame } = render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
92
+ const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
93
93
  // Should immediately show loading state
94
94
  const output = lastFrame();
95
95
  expect(output).toContain('Loading branches...');
@@ -114,7 +114,7 @@ describe('NewWorktree component Effect integration', () => {
114
114
  });
115
115
  const onComplete = vi.fn();
116
116
  const onCancel = vi.fn();
117
- const { lastFrame } = render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
117
+ const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
118
118
  // Wait for Effect to execute
119
119
  await new Promise(resolve => setTimeout(resolve, 100));
120
120
  const output = lastFrame();
@@ -138,7 +138,7 @@ describe('NewWorktree component Effect integration', () => {
138
138
  });
139
139
  const onComplete = vi.fn();
140
140
  const onCancel = vi.fn();
141
- render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
141
+ render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
142
142
  // Wait for Effect to execute
143
143
  await new Promise(resolve => setTimeout(resolve, 100));
144
144
  // Verify both Effect-based methods were called (parallel execution via Effect.all)
@@ -164,7 +164,7 @@ describe('NewWorktree component Effect integration', () => {
164
164
  });
165
165
  const onComplete = vi.fn();
166
166
  const onCancel = vi.fn();
167
- const { lastFrame } = render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
167
+ const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
168
168
  // Wait for Effect to execute
169
169
  await new Promise(resolve => setTimeout(resolve, 100));
170
170
  const output = lastFrame();
@@ -191,7 +191,7 @@ describe('NewWorktree component Effect integration', () => {
191
191
  });
192
192
  const onComplete = vi.fn();
193
193
  const onCancel = vi.fn();
194
- const { lastFrame } = render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
194
+ const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
195
195
  // Wait for Effect to execute
196
196
  await new Promise(resolve => setTimeout(resolve, 100));
197
197
  const output = lastFrame();
@@ -221,7 +221,7 @@ describe('NewWorktree component Effect integration', () => {
221
221
  });
222
222
  const onComplete = vi.fn();
223
223
  const onCancel = vi.fn();
224
- const { lastFrame } = render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
224
+ const { lastFrame } = render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
225
225
  // Wait for Effect to execute
226
226
  await new Promise(resolve => setTimeout(resolve, 100));
227
227
  const output = lastFrame();
@@ -253,7 +253,7 @@ describe('NewWorktree component Effect integration', () => {
253
253
  });
254
254
  const onComplete = vi.fn();
255
255
  const onCancel = vi.fn();
256
- render(React.createElement(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
256
+ render(_jsx(NewWorktree, { onComplete: onComplete, onCancel: onCancel }));
257
257
  // Wait for Effect to execute
258
258
  await new Promise(resolve => setTimeout(resolve, 100));
259
259
  // Verify Effect was executed (Effect.match pattern)
@@ -1,4 +1,5 @@
1
- import React, { useState } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
2
3
  import { Box, Text, useInput } from 'ink';
3
4
  import SelectInput from 'ink-select-input';
4
5
  import { configReader } from '../services/config/configReader.js';
@@ -40,13 +41,6 @@ const PresetSelector = ({ onSelect, onCancel, }) => {
40
41
  onCancel();
41
42
  }
42
43
  });
43
- return (React.createElement(Box, { flexDirection: "column" },
44
- React.createElement(Box, { marginBottom: 1 },
45
- React.createElement(Text, { bold: true, color: "green" }, "Select Command Preset")),
46
- React.createElement(Box, { marginBottom: 1 },
47
- React.createElement(Text, { dimColor: true }, "Choose a preset to start the session with")),
48
- React.createElement(SelectInput, { items: selectItems, onSelect: handleSelectItem, initialIndex: initialIndex >= 0 ? initialIndex : 0 }),
49
- React.createElement(Box, { marginTop: 1 },
50
- React.createElement(Text, { dimColor: true }, "Press \u2191\u2193 to navigate, Enter to select, ESC to cancel"))));
44
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "Select Command Preset" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a preset to start the session with" }) }), _jsx(SelectInput, { items: selectItems, onSelect: handleSelectItem, initialIndex: initialIndex >= 0 ? initialIndex : 0 }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press \u2191\u2193 to navigate, Enter to select, ESC to cancel" }) })] }));
51
45
  };
52
46
  export default PresetSelector;
@@ -1,4 +1,5 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
2
3
  import { Box, Text, useInput } from 'ink';
3
4
  import { Effect } from 'effect';
4
5
  import SelectInput from 'ink-select-input';
@@ -221,42 +222,12 @@ const ProjectList = ({ projectsDir, onSelectProject, error, onDismissError, }) =
221
222
  onSelectProject(item.project);
222
223
  }
223
224
  };
224
- return (React.createElement(Box, { flexDirection: "column" },
225
- React.createElement(Box, { marginBottom: 1 },
226
- React.createElement(Text, { bold: true, color: "green" }, "CCManager - Multi-Project Mode")),
227
- React.createElement(Box, { marginBottom: 1 },
228
- React.createElement(Text, { dimColor: true }, "Select a project:")),
229
- isSearchMode && (React.createElement(Box, { marginBottom: 1 },
230
- React.createElement(Text, null, "Search: "),
231
- React.createElement(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter projects..." }))),
232
- loading ? (React.createElement(Box, null,
233
- React.createElement(Text, { color: "yellow" }, "Loading projects..."))) : projects.length === 0 && !displayError ? (React.createElement(Box, null,
234
- React.createElement(Text, { color: "yellow" },
235
- "No git repositories found in ",
236
- projectsDir))) : isSearchMode && items.length === 0 ? (React.createElement(Box, null,
237
- React.createElement(Text, { color: "yellow" }, "No projects match your search"))) : isSearchMode ? (
238
- // In search mode, show the items as a list without SelectInput
239
- React.createElement(Box, { flexDirection: "column" }, items.slice(0, limit).map((item, index) => (React.createElement(Text, { key: item.value, color: index === selectedIndex ? 'green' : undefined },
240
- index === selectedIndex ? '❯ ' : ' ',
241
- item.label))))) : (React.createElement(SelectInput, { items: items, onSelect: handleSelect, isFocused: !displayError, limit: limit, initialIndex: selectedIndex })),
242
- displayError && (React.createElement(Box, { marginTop: 1, paddingX: 1, borderStyle: "round", borderColor: "red" },
243
- React.createElement(Box, { flexDirection: "column" },
244
- React.createElement(Text, { color: "red", bold: true },
245
- "Error: ",
246
- displayError),
247
- React.createElement(Text, { color: "gray", dimColor: true }, "Press any key to dismiss")))),
248
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
249
- (isSearchMode || searchQuery) && (React.createElement(Text, { dimColor: true },
250
- "Projects: ",
251
- items.filter(item => item.project).length,
252
- " of",
253
- ' ',
254
- projects.length,
255
- " shown")),
256
- React.createElement(Text, { dimColor: true }, isSearchMode
257
- ? 'Search Mode: Type to filter, Enter to exit search, ESC to exit search'
258
- : searchQuery
259
- ? `Filtered: "${searchQuery}" | ↑↓ Navigate Enter Select | /-Search ESC-Clear 0-9 Quick Select R-Refresh Q-Quit`
260
- : 'Controls: ↑↓ Navigate Enter Select | Hotkeys: 0-9 Quick Select /-Search R-Refresh Q-Quit'))));
225
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, color: "green", children: "CCManager - Multi-Project Mode" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Select a project:" }) }), isSearchMode && (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { children: "Search: " }), _jsx(TextInputWrapper, { value: searchQuery, onChange: setSearchQuery, focus: true, placeholder: "Type to filter projects..." })] })), loading ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "Loading projects..." }) })) : projects.length === 0 && !displayError ? (_jsx(Box, { children: _jsxs(Text, { color: "yellow", children: ["No git repositories found in ", projectsDir] }) })) : isSearchMode && items.length === 0 ? (_jsx(Box, { children: _jsx(Text, { color: "yellow", children: "No projects match your search" }) })) : isSearchMode ? (
226
+ // In search mode, show the items as a list without SelectInput
227
+ _jsx(Box, { flexDirection: "column", children: items.slice(0, limit).map((item, index) => (_jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', item.label] }, item.value))) })) : (_jsx(SelectInput, { items: items, onSelect: handleSelect, isFocused: !displayError, limit: limit, initialIndex: selectedIndex })), displayError && (_jsx(Box, { marginTop: 1, paddingX: 1, borderStyle: "round", borderColor: "red", children: _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "red", bold: true, children: ["Error: ", displayError] }), _jsx(Text, { color: "gray", dimColor: true, children: "Press any key to dismiss" })] }) })), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [(isSearchMode || searchQuery) && (_jsxs(Text, { dimColor: true, children: ["Projects: ", items.filter(item => item.project).length, " of", ' ', projects.length, " shown"] })), _jsx(Text, { dimColor: true, children: isSearchMode
228
+ ? 'Search Mode: Type to filter, Enter to exit search, ESC to exit search'
229
+ : searchQuery
230
+ ? `Filtered: "${searchQuery}" | ↑↓ Navigate Enter Select | /-Search ESC-Clear 0-9 Quick Select R-Refresh Q-Quit`
231
+ : 'Controls: ↑↓ Navigate Enter Select | Hotkeys: 0-9 Quick Select /-Search R-Refresh Q-Quit' })] })] }));
261
232
  };
262
233
  export default ProjectList;
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { render } from 'ink-testing-library';
3
3
  import { expect, describe, it, vi, beforeEach, afterEach } from 'vitest';
4
4
  import ProjectList from './ProjectList.js';
@@ -24,7 +24,7 @@ vi.mock('ink-select-input', async () => {
24
24
  const { Text, Box } = await vi.importActual('ink');
25
25
  return {
26
26
  default: ({ items }) => {
27
- return (React.createElement(Box, { flexDirection: "column" }, items.map(item => (React.createElement(Text, { key: item.value }, item.label)))));
27
+ return (_jsx(Box, { flexDirection: "column", children: items.map(item => (_jsx(Text, { children: item.label }, item.value))) }));
28
28
  },
29
29
  };
30
30
  });
@@ -79,7 +79,7 @@ describe('ProjectList - Recent Projects', () => {
79
79
  lastAccessed: Date.now() - 2000,
80
80
  },
81
81
  ]);
82
- const { lastFrame } = render(React.createElement(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
82
+ const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
83
83
  // Wait for projects to load
84
84
  await vi.waitFor(() => {
85
85
  expect(lastFrame()).toContain('project-c');
@@ -97,7 +97,7 @@ describe('ProjectList - Recent Projects', () => {
97
97
  });
98
98
  it('should not show recent projects section when there are none', async () => {
99
99
  vi.mocked(projectManager.getRecentProjects).mockReturnValue([]);
100
- const { lastFrame } = render(React.createElement(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
100
+ const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
101
101
  // Wait for projects to load
102
102
  await vi.waitFor(() => {
103
103
  expect(lastFrame()).toContain('project-a');
@@ -127,7 +127,7 @@ describe('ProjectList - Recent Projects', () => {
127
127
  lastAccessed: Date.now() - 2000,
128
128
  },
129
129
  ]);
130
- const { lastFrame } = render(React.createElement(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
130
+ const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
131
131
  // Wait for projects to load
132
132
  await vi.waitFor(() => {
133
133
  expect(lastFrame()).toContain('project-c');
@@ -151,7 +151,7 @@ describe('ProjectList - Recent Projects', () => {
151
151
  lastAccessed: Date.now() - i * 1000,
152
152
  }));
153
153
  vi.mocked(projectManager.getRecentProjects).mockReturnValue(manyRecentProjects);
154
- const { lastFrame } = render(React.createElement(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
154
+ const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
155
155
  // Wait for projects to load
156
156
  await vi.waitFor(() => {
157
157
  expect(lastFrame()).toContain('project-0');
@@ -177,7 +177,7 @@ describe('ProjectList - Recent Projects', () => {
177
177
  mockUseInput.mockImplementation(handler => {
178
178
  inputHandler = handler;
179
179
  });
180
- const { lastFrame } = render(React.createElement(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
180
+ const { lastFrame } = render(_jsx(ProjectList, { projectsDir: "/home/user/projects", onSelectProject: mockOnSelectProject, error: null, onDismissError: mockOnDismissError }));
181
181
  // Wait for projects to load
182
182
  await vi.waitFor(() => {
183
183
  expect(lastFrame()).toContain('project-c');