ccmanager 0.1.9 → 0.1.11
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/README.md +1 -11
- package/dist/components/DeleteWorktree.js +6 -3
- package/dist/components/Menu.js +3 -1
- package/dist/components/MergeWorktree.js +2 -2
- package/dist/components/NewWorktree.js +2 -2
- package/dist/services/worktreeService.js +37 -26
- package/dist/types/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,18 +54,8 @@ $ npx ccmanager
|
|
|
54
54
|
|
|
55
55
|
### CCMANAGER_CLAUDE_ARGS
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
⚠️ **Deprecated in v0.1.9**: `CCMANAGER_CLAUDE_ARGS` is no longer supported. Please use the [Command Configuration](#command-configuration) feature instead.
|
|
58
58
|
|
|
59
|
-
```bash
|
|
60
|
-
# Start Claude Code with specific arguments for all sessions
|
|
61
|
-
export CCMANAGER_CLAUDE_ARGS="--resume"
|
|
62
|
-
npx ccmanager
|
|
63
|
-
|
|
64
|
-
# Or set it inline
|
|
65
|
-
CCMANAGER_CLAUDE_ARGS="--resume" npx ccmanager
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
The arguments are applied to all Claude Code sessions started by CCManager.
|
|
69
59
|
|
|
70
60
|
## Keyboard Shortcuts
|
|
71
61
|
|
|
@@ -75,8 +75,9 @@ const DeleteWorktree = ({ onComplete, onCancel, }) => {
|
|
|
75
75
|
React.createElement(Text, null, "You are about to delete the following worktrees:"),
|
|
76
76
|
selectedWorktrees.map(wt => (React.createElement(Text, { key: wt.path, color: "red" },
|
|
77
77
|
"\u2022 ",
|
|
78
|
-
wt.branch.replace('refs/heads/', ''),
|
|
79
|
-
|
|
78
|
+
wt.branch ? wt.branch.replace('refs/heads/', '') : 'detached',
|
|
79
|
+
' ',
|
|
80
|
+
"(",
|
|
80
81
|
wt.path,
|
|
81
82
|
")")))),
|
|
82
83
|
React.createElement(Text, { bold: true }, "This will also delete their branches. Are you sure?")));
|
|
@@ -90,7 +91,9 @@ const DeleteWorktree = ({ onComplete, onCancel, }) => {
|
|
|
90
91
|
worktrees.map((worktree, index) => {
|
|
91
92
|
const isSelected = selectedIndices.has(index);
|
|
92
93
|
const isFocused = index === focusedIndex;
|
|
93
|
-
const branchName = worktree.branch
|
|
94
|
+
const branchName = worktree.branch
|
|
95
|
+
? worktree.branch.replace('refs/heads/', '')
|
|
96
|
+
: 'detached';
|
|
94
97
|
return (React.createElement(Box, { key: worktree.path },
|
|
95
98
|
React.createElement(Text, { color: isFocused ? 'green' : undefined, inverse: isFocused, dimColor: !isFocused && !isSelected },
|
|
96
99
|
isSelected ? '[✓]' : '[ ]',
|
package/dist/components/Menu.js
CHANGED
|
@@ -41,7 +41,9 @@ const Menu = ({ sessionManager, onSelectWorktree }) => {
|
|
|
41
41
|
if (session) {
|
|
42
42
|
status = ` [${getStatusDisplay(session.state)}]`;
|
|
43
43
|
}
|
|
44
|
-
const branchName = wt.branch
|
|
44
|
+
const branchName = wt.branch
|
|
45
|
+
? wt.branch.replace('refs/heads/', '')
|
|
46
|
+
: 'detached';
|
|
45
47
|
const isMain = wt.isMainWorktree ? ' (main)' : '';
|
|
46
48
|
return {
|
|
47
49
|
label: `${branchName}${isMain}${status}`,
|
|
@@ -16,9 +16,9 @@ const MergeWorktree = ({ onComplete, onCancel, }) => {
|
|
|
16
16
|
const loadedWorktrees = worktreeService.getWorktrees();
|
|
17
17
|
// Create branch items for selection
|
|
18
18
|
const items = loadedWorktrees.map(wt => ({
|
|
19
|
-
label: wt.branch.replace('refs/heads/', '') +
|
|
19
|
+
label: (wt.branch ? wt.branch.replace('refs/heads/', '') : 'detached') +
|
|
20
20
|
(wt.isMainWorktree ? ' (main)' : ''),
|
|
21
|
-
value: wt.branch.replace('refs/heads/', ''),
|
|
21
|
+
value: wt.branch ? wt.branch.replace('refs/heads/', '') : 'detached',
|
|
22
22
|
}));
|
|
23
23
|
setBranchItems(items);
|
|
24
24
|
}, []);
|
|
@@ -79,7 +79,7 @@ const NewWorktree = ({ onComplete, onCancel }) => {
|
|
|
79
79
|
":")),
|
|
80
80
|
React.createElement(Box, null,
|
|
81
81
|
React.createElement(Text, { color: "cyan" }, '> '),
|
|
82
|
-
React.createElement(TextInput, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })))) : (React.createElement(Box, { flexDirection: "column" },
|
|
82
|
+
React.createElement(TextInput, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })))) : step === 'branch' ? (React.createElement(Box, { flexDirection: "column" },
|
|
83
83
|
React.createElement(Box, { marginBottom: 1 },
|
|
84
84
|
React.createElement(Text, null, "Enter branch name (directory will be auto-generated):")),
|
|
85
85
|
React.createElement(Box, null,
|
|
@@ -89,7 +89,7 @@ const NewWorktree = ({ onComplete, onCancel }) => {
|
|
|
89
89
|
React.createElement(Text, { dimColor: true },
|
|
90
90
|
"Worktree will be created at:",
|
|
91
91
|
' ',
|
|
92
|
-
React.createElement(Text, { color: "green" }, generatedPath)))))),
|
|
92
|
+
React.createElement(Text, { color: "green" }, generatedPath)))))) : null,
|
|
93
93
|
step === 'base-branch' && (React.createElement(Box, { flexDirection: "column" },
|
|
94
94
|
React.createElement(Box, { marginBottom: 1 },
|
|
95
95
|
React.createElement(Text, null,
|
|
@@ -42,32 +42,41 @@ export class WorktreeService {
|
|
|
42
42
|
});
|
|
43
43
|
const worktrees = [];
|
|
44
44
|
const lines = output.trim().split('\n');
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
worktrees.push(currentWorktree);
|
|
50
|
-
}
|
|
51
|
-
currentWorktree = {
|
|
52
|
-
path: line.substring(9),
|
|
53
|
-
isMainWorktree: false,
|
|
54
|
-
hasSession: false,
|
|
55
|
-
};
|
|
45
|
+
const parseWorktree = (lines, startIndex) => {
|
|
46
|
+
const worktreeLine = lines[startIndex];
|
|
47
|
+
if (!worktreeLine?.startsWith('worktree ')) {
|
|
48
|
+
return [null, startIndex];
|
|
56
49
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
const worktree = {
|
|
51
|
+
path: worktreeLine.substring(9),
|
|
52
|
+
isMainWorktree: false,
|
|
53
|
+
hasSession: false,
|
|
54
|
+
};
|
|
55
|
+
let i = startIndex + 1;
|
|
56
|
+
while (i < lines.length &&
|
|
57
|
+
lines[i] &&
|
|
58
|
+
!lines[i].startsWith('worktree ')) {
|
|
59
|
+
const line = lines[i];
|
|
60
|
+
if (line && line.startsWith('branch ')) {
|
|
61
|
+
const branch = line.substring(7);
|
|
62
|
+
worktree.branch = branch.startsWith('refs/heads/')
|
|
63
|
+
? branch.substring(11)
|
|
64
|
+
: branch;
|
|
62
65
|
}
|
|
63
|
-
|
|
66
|
+
else if (line === 'bare') {
|
|
67
|
+
worktree.isMainWorktree = true;
|
|
68
|
+
}
|
|
69
|
+
i++;
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
return [worktree, i];
|
|
72
|
+
};
|
|
73
|
+
let index = 0;
|
|
74
|
+
while (index < lines.length) {
|
|
75
|
+
const [worktree, nextIndex] = parseWorktree(lines, index);
|
|
76
|
+
if (worktree) {
|
|
77
|
+
worktrees.push(worktree);
|
|
67
78
|
}
|
|
68
|
-
|
|
69
|
-
if (currentWorktree.path) {
|
|
70
|
-
worktrees.push(currentWorktree);
|
|
79
|
+
index = nextIndex > index ? nextIndex : index + 1;
|
|
71
80
|
}
|
|
72
81
|
// Mark the first worktree as main if none are marked
|
|
73
82
|
if (worktrees.length > 0 && !worktrees.some(w => w.isMainWorktree)) {
|
|
@@ -224,7 +233,9 @@ export class WorktreeService {
|
|
|
224
233
|
encoding: 'utf8',
|
|
225
234
|
});
|
|
226
235
|
// Delete the branch if it exists
|
|
227
|
-
const branchName = worktree.branch
|
|
236
|
+
const branchName = worktree.branch
|
|
237
|
+
? worktree.branch.replace('refs/heads/', '')
|
|
238
|
+
: 'detached';
|
|
228
239
|
try {
|
|
229
240
|
execSync(`git branch -D "${branchName}"`, {
|
|
230
241
|
cwd: this.rootPath,
|
|
@@ -248,7 +259,7 @@ export class WorktreeService {
|
|
|
248
259
|
try {
|
|
249
260
|
// Get worktrees to find the target worktree path
|
|
250
261
|
const worktrees = this.getWorktrees();
|
|
251
|
-
const targetWorktree = worktrees.find(wt => wt.branch.replace('refs/heads/', '') === targetBranch);
|
|
262
|
+
const targetWorktree = worktrees.find(wt => wt.branch && wt.branch.replace('refs/heads/', '') === targetBranch);
|
|
252
263
|
if (!targetWorktree) {
|
|
253
264
|
return {
|
|
254
265
|
success: false,
|
|
@@ -258,7 +269,7 @@ export class WorktreeService {
|
|
|
258
269
|
// Perform the merge or rebase in the target worktree
|
|
259
270
|
if (useRebase) {
|
|
260
271
|
// For rebase, we need to checkout source branch and rebase it onto target
|
|
261
|
-
const sourceWorktree = worktrees.find(wt => wt.branch.replace('refs/heads/', '') === sourceBranch);
|
|
272
|
+
const sourceWorktree = worktrees.find(wt => wt.branch && wt.branch.replace('refs/heads/', '') === sourceBranch);
|
|
262
273
|
if (!sourceWorktree) {
|
|
263
274
|
return {
|
|
264
275
|
success: false,
|
|
@@ -300,7 +311,7 @@ export class WorktreeService {
|
|
|
300
311
|
try {
|
|
301
312
|
// Get worktrees to find the worktree by branch
|
|
302
313
|
const worktrees = this.getWorktrees();
|
|
303
|
-
const worktree = worktrees.find(wt => wt.branch.replace('refs/heads/', '') === branch);
|
|
314
|
+
const worktree = worktrees.find(wt => wt.branch && wt.branch.replace('refs/heads/', '') === branch);
|
|
304
315
|
if (!worktree) {
|
|
305
316
|
return {
|
|
306
317
|
success: false,
|
package/dist/types/index.d.ts
CHANGED