ccmanager 3.3.0 → 3.3.1
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 +12 -11
- package/dist/components/ConfigureCommand.js +66 -40
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -112,23 +112,24 @@ Note: Shortcuts from `shortcuts.json` will be automatically migrated to `config.
|
|
|
112
112
|
|
|
113
113
|
## Supported AI Assistants
|
|
114
114
|
|
|
115
|
-
CCManager
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
115
|
+
CCManager supports multiple AI coding assistants with tailored state detection for each:
|
|
116
|
+
|
|
117
|
+
| Assistant | Command | Installation |
|
|
118
|
+
|-----------|---------|--------------|
|
|
119
|
+
| Claude Code (Default) | `claude` | [code.claude.com](https://code.claude.com/docs/en/setup) |
|
|
120
|
+
| Gemini CLI | `gemini` | [github.com/google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli) |
|
|
121
|
+
| Codex CLI | `codex` | [github.com/openai/codex](https://github.com/openai/codex) |
|
|
122
|
+
| Cursor Agent | `cursor-agent` | [cursor.com/cli](https://cursor.com/docs/cli/overview) |
|
|
123
|
+
| Copilot CLI | `copilot` | [github.com/github/copilot-cli](https://github.com/github/copilot-cli) |
|
|
124
|
+
| Cline CLI | `cline` | [github.com/cline/cline](https://github.com/cline/cline) |
|
|
125
|
+
| OpenCode | `opencode` | [opencode.ai/docs](https://opencode.ai/docs) |
|
|
125
126
|
|
|
126
127
|
Each assistant has its own state detection strategy to properly track:
|
|
127
128
|
- **Idle**: Ready for new input
|
|
128
129
|
- **Busy**: Processing a request
|
|
129
130
|
- **Waiting**: Awaiting user confirmation
|
|
130
131
|
|
|
131
|
-
See [Gemini Support Documentation](docs/gemini-support.md) for
|
|
132
|
+
See [Gemini Support Documentation](docs/gemini-support.md) for CCManager-specific configuration.
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
## Command Configuration
|
|
@@ -25,6 +25,16 @@ const createStrategyItems = () => {
|
|
|
25
25
|
};
|
|
26
26
|
// Type-safe strategy items that ensures all StateDetectionStrategy values are included
|
|
27
27
|
const ALL_STRATEGY_ITEMS = createStrategyItems();
|
|
28
|
+
// Default command mapping for each strategy
|
|
29
|
+
const DEFAULT_COMMANDS = {
|
|
30
|
+
claude: 'claude',
|
|
31
|
+
gemini: 'gemini',
|
|
32
|
+
codex: 'codex',
|
|
33
|
+
cursor: 'cursor',
|
|
34
|
+
'github-copilot': 'copilot',
|
|
35
|
+
cline: 'cline',
|
|
36
|
+
opencode: 'opencode',
|
|
37
|
+
};
|
|
28
38
|
const formatDetectionStrategy = (strategy) => {
|
|
29
39
|
const value = strategy || 'claude';
|
|
30
40
|
switch (value) {
|
|
@@ -57,7 +67,7 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
57
67
|
const [isSelectingStrategy, setIsSelectingStrategy] = useState(false);
|
|
58
68
|
const [isSelectingStrategyInAdd, setIsSelectingStrategyInAdd] = useState(false);
|
|
59
69
|
const [newPreset, setNewPreset] = useState({});
|
|
60
|
-
const [addStep, setAddStep] = useState('
|
|
70
|
+
const [addStep, setAddStep] = useState('detectionStrategy');
|
|
61
71
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
62
72
|
// Remove handleListNavigation as SelectInput handles navigation internally
|
|
63
73
|
// Remove handleListSelection as we now use handleSelectItem
|
|
@@ -142,19 +152,8 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
142
152
|
};
|
|
143
153
|
const handleAddPresetInput = (value) => {
|
|
144
154
|
switch (addStep) {
|
|
145
|
-
case 'name':
|
|
146
|
-
// Prevent using "Default" as a name to avoid confusion
|
|
147
|
-
if (value.trim().toLowerCase() === 'default') {
|
|
148
|
-
setErrorMessage('Cannot use "Default" as a preset name. Please choose a different name.');
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
setNewPreset({ ...newPreset, name: value });
|
|
152
|
-
setAddStep('command');
|
|
153
|
-
setInputValue('');
|
|
154
|
-
setErrorMessage(null);
|
|
155
|
-
break;
|
|
156
155
|
case 'command':
|
|
157
|
-
setNewPreset({ ...newPreset, command: value
|
|
156
|
+
setNewPreset({ ...newPreset, command: value });
|
|
158
157
|
setAddStep('args');
|
|
159
158
|
setInputValue('');
|
|
160
159
|
break;
|
|
@@ -170,8 +169,38 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
170
169
|
? value.trim().split(/\s+/)
|
|
171
170
|
: undefined;
|
|
172
171
|
setNewPreset({ ...newPreset, fallbackArgs });
|
|
172
|
+
setAddStep('name');
|
|
173
|
+
setInputValue('');
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case 'name': {
|
|
177
|
+
if (!value.trim()) {
|
|
178
|
+
setErrorMessage('Preset name cannot be empty. Please enter a name.');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (value.trim().toLowerCase() === 'default') {
|
|
182
|
+
setErrorMessage('Cannot use "Default" as a preset name. Please choose a different name.');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const id = Date.now().toString();
|
|
186
|
+
const completePreset = {
|
|
187
|
+
id,
|
|
188
|
+
name: value,
|
|
189
|
+
command: newPreset.command || 'claude',
|
|
190
|
+
args: newPreset.args,
|
|
191
|
+
fallbackArgs: newPreset.fallbackArgs,
|
|
192
|
+
detectionStrategy: newPreset.detectionStrategy || 'claude',
|
|
193
|
+
};
|
|
194
|
+
const updatedPresets = [...presets, completePreset];
|
|
195
|
+
setPresets(updatedPresets);
|
|
196
|
+
configurationManager.addPreset(completePreset);
|
|
197
|
+
setViewMode('list');
|
|
198
|
+
setSelectedIndex(updatedPresets.length - 1);
|
|
199
|
+
setNewPreset({});
|
|
173
200
|
setAddStep('detectionStrategy');
|
|
174
|
-
|
|
201
|
+
setInputValue('');
|
|
202
|
+
setIsSelectingStrategyInAdd(false);
|
|
203
|
+
setErrorMessage(null);
|
|
175
204
|
break;
|
|
176
205
|
}
|
|
177
206
|
}
|
|
@@ -188,25 +217,16 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
188
217
|
setIsSelectingStrategy(false);
|
|
189
218
|
};
|
|
190
219
|
const handleAddStrategySelect = (item) => {
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const updatedPresets = [...presets, completePreset];
|
|
201
|
-
setPresets(updatedPresets);
|
|
202
|
-
configurationManager.addPreset(completePreset);
|
|
203
|
-
setViewMode('list');
|
|
204
|
-
setSelectedIndex(updatedPresets.length - 1);
|
|
205
|
-
setNewPreset({});
|
|
206
|
-
setAddStep('name');
|
|
207
|
-
setInputValue('');
|
|
220
|
+
const strategy = item.value;
|
|
221
|
+
const defaultCommand = DEFAULT_COMMANDS[strategy];
|
|
222
|
+
setNewPreset({
|
|
223
|
+
...newPreset,
|
|
224
|
+
detectionStrategy: strategy,
|
|
225
|
+
command: defaultCommand,
|
|
226
|
+
});
|
|
227
|
+
setAddStep('command');
|
|
228
|
+
setInputValue(defaultCommand);
|
|
208
229
|
setIsSelectingStrategyInAdd(false);
|
|
209
|
-
setErrorMessage(null);
|
|
210
230
|
};
|
|
211
231
|
const handleDeleteConfirm = () => {
|
|
212
232
|
if (selectedIndex === 0) {
|
|
@@ -239,7 +259,7 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
239
259
|
else if (isSelectingStrategyInAdd) {
|
|
240
260
|
setIsSelectingStrategyInAdd(false);
|
|
241
261
|
setViewMode('list');
|
|
242
|
-
setAddStep('
|
|
262
|
+
setAddStep('detectionStrategy');
|
|
243
263
|
setNewPreset({});
|
|
244
264
|
}
|
|
245
265
|
else if (editField) {
|
|
@@ -338,6 +358,8 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
338
358
|
React.createElement(Text, { bold: true, color: "green" }, "Add New Preset - Detection Strategy")),
|
|
339
359
|
React.createElement(Box, { marginBottom: 1 },
|
|
340
360
|
React.createElement(Text, null, "Choose the state detection strategy for this preset:")),
|
|
361
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
362
|
+
React.createElement(Text, { dimColor: true }, "The command will be auto-set based on the strategy (can be changed later)")),
|
|
341
363
|
React.createElement(SelectInput, { items: strategyItems, onSelect: handleAddStrategySelect, initialIndex: 0 }),
|
|
342
364
|
React.createElement(Box, { marginTop: 1 },
|
|
343
365
|
React.createElement(Text, { dimColor: true },
|
|
@@ -347,23 +369,26 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
347
369
|
" to cancel"))));
|
|
348
370
|
}
|
|
349
371
|
const titles = {
|
|
350
|
-
|
|
351
|
-
command: 'Enter command (
|
|
372
|
+
detectionStrategy: 'Select detection strategy:',
|
|
373
|
+
command: 'Enter command (default set by strategy, can be modified):',
|
|
352
374
|
args: 'Enter command arguments (space-separated):',
|
|
353
375
|
fallbackArgs: 'Enter fallback arguments (space-separated):',
|
|
376
|
+
name: 'Enter preset name (freely customizable):',
|
|
354
377
|
};
|
|
355
378
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
356
379
|
React.createElement(Box, { marginBottom: 1 },
|
|
357
380
|
React.createElement(Text, { bold: true, color: "green" }, "Add New Preset")),
|
|
358
381
|
React.createElement(Box, { marginBottom: 1 },
|
|
359
382
|
React.createElement(Text, null, titles[addStep])),
|
|
383
|
+
addStep === 'command' && (React.createElement(Box, { marginBottom: 1 },
|
|
384
|
+
React.createElement(Text, { dimColor: true }, "Auto-filled from your strategy selection. You can change this if needed."))),
|
|
360
385
|
errorMessage && (React.createElement(Box, { marginBottom: 1 },
|
|
361
386
|
React.createElement(Text, { color: "red" }, errorMessage))),
|
|
362
387
|
React.createElement(Box, null,
|
|
363
|
-
React.createElement(TextInputWrapper, { value: inputValue, onChange: setInputValue, onSubmit: handleAddPresetInput, placeholder: addStep === '
|
|
364
|
-
? 'e.g.,
|
|
365
|
-
: addStep === '
|
|
366
|
-
? 'e.g.,
|
|
388
|
+
React.createElement(TextInputWrapper, { value: inputValue, onChange: setInputValue, onSubmit: handleAddPresetInput, placeholder: addStep === 'name'
|
|
389
|
+
? 'e.g., Development'
|
|
390
|
+
: addStep === 'args' || addStep === 'fallbackArgs'
|
|
391
|
+
? 'e.g., --resume or leave empty'
|
|
367
392
|
: '' })),
|
|
368
393
|
React.createElement(Box, { marginTop: 1 },
|
|
369
394
|
React.createElement(Text, { dimColor: true },
|
|
@@ -494,7 +519,8 @@ const ConfigureCommand = ({ onComplete }) => {
|
|
|
494
519
|
// Add New Preset
|
|
495
520
|
setViewMode('add');
|
|
496
521
|
setNewPreset({});
|
|
497
|
-
setAddStep('
|
|
522
|
+
setAddStep('detectionStrategy');
|
|
523
|
+
setIsSelectingStrategyInAdd(true);
|
|
498
524
|
setInputValue('');
|
|
499
525
|
}
|
|
500
526
|
else if (item.value === 'exit') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccmanager",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kodai Kabasawa",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"bin"
|
|
42
42
|
],
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@kodaikabasawa/ccmanager-darwin-arm64": "3.3.
|
|
45
|
-
"@kodaikabasawa/ccmanager-darwin-x64": "3.3.
|
|
46
|
-
"@kodaikabasawa/ccmanager-linux-arm64": "3.3.
|
|
47
|
-
"@kodaikabasawa/ccmanager-linux-x64": "3.3.
|
|
48
|
-
"@kodaikabasawa/ccmanager-win32-x64": "3.3.
|
|
44
|
+
"@kodaikabasawa/ccmanager-darwin-arm64": "3.3.1",
|
|
45
|
+
"@kodaikabasawa/ccmanager-darwin-x64": "3.3.1",
|
|
46
|
+
"@kodaikabasawa/ccmanager-linux-arm64": "3.3.1",
|
|
47
|
+
"@kodaikabasawa/ccmanager-linux-x64": "3.3.1",
|
|
48
|
+
"@kodaikabasawa/ccmanager-win32-x64": "3.3.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@eslint/js": "^9.28.0",
|
|
@@ -68,14 +68,14 @@
|
|
|
68
68
|
},
|
|
69
69
|
"prettier": "@vdemedes/prettier-config",
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@xterm/headless": "^
|
|
71
|
+
"@xterm/headless": "^6.0.0",
|
|
72
72
|
"effect": "^3.18.2",
|
|
73
73
|
"ink": "5.2.1",
|
|
74
74
|
"ink-select-input": "^6.0.0",
|
|
75
75
|
"ink-text-input": "^6.0.0",
|
|
76
76
|
"meow": "^11.0.0",
|
|
77
77
|
"react": "18.3.1",
|
|
78
|
-
"react-devtools-core": "^
|
|
78
|
+
"react-devtools-core": "^7.0.1",
|
|
79
79
|
"react-dom": "18.3.1",
|
|
80
80
|
"strip-ansi": "^7.1.0"
|
|
81
81
|
}
|