ccmanager 0.2.0 → 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/README.md CHANGED
@@ -1,17 +1,19 @@
1
- # CCManager - Claude Code Session Manager
1
+ # CCManager - AI Code Assistant Session Manager
2
2
 
3
- CCManager is a TUI application for managing multiple Claude Code sessions across Git worktrees.
3
+ CCManager is a TUI application for managing multiple AI coding assistant sessions (Claude Code, Gemini CLI) across Git worktrees.
4
4
 
5
5
  https://github.com/user-attachments/assets/a6d80e73-dc06-4ef8-849d-e3857f6c7024
6
6
 
7
7
  ## Features
8
8
 
9
- - Run multiple Claude Code sessions in parallel across different Git worktrees
9
+ - Run multiple AI assistant sessions in parallel across different Git worktrees
10
+ - Support for multiple AI coding assistants (Claude Code, Gemini CLI)
10
11
  - Switch between sessions seamlessly
11
12
  - Visual status indicators for session states (busy, waiting, idle)
12
13
  - Create, merge, and delete worktrees from within the app
13
14
  - Configurable keyboard shortcuts
14
- - Command configuration with automatic fallback support
15
+ - Command presets with automatic fallback support
16
+ - Configurable state detection strategies for different CLI tools
15
17
  - Status change hooks for automation and notifications
16
18
 
17
19
  ## Why CCManager over Claude Squad?
@@ -108,6 +110,26 @@ Note: Shortcuts from `shortcuts.json` will be automatically migrated to `config.
108
110
  - Ctrl+D
109
111
  - Ctrl+[ (equivalent to Escape)
110
112
 
113
+ ## Supported AI Assistants
114
+
115
+ CCManager now supports multiple AI coding assistants with tailored state detection:
116
+
117
+ ### Claude Code (Default)
118
+ - Command: `claude`
119
+ - State detection: Built-in patterns for Claude's prompts and status messages
120
+
121
+ ### Gemini CLI
122
+ - Command: `gemini`
123
+ - State detection: Custom patterns for Gemini's confirmation prompts
124
+ - Installation: [google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli)
125
+
126
+ Each assistant has its own state detection strategy to properly track:
127
+ - **Idle**: Ready for new input
128
+ - **Busy**: Processing a request
129
+ - **Waiting**: Awaiting user confirmation
130
+
131
+ See [Gemini Support Documentation](docs/gemini-support.md) for detailed configuration instructions.
132
+
111
133
 
112
134
  ## Command Configuration
113
135
 
@@ -6,9 +6,11 @@ import NewWorktree from './NewWorktree.js';
6
6
  import DeleteWorktree from './DeleteWorktree.js';
7
7
  import MergeWorktree from './MergeWorktree.js';
8
8
  import Configuration from './Configuration.js';
9
+ import PresetSelector from './PresetSelector.js';
9
10
  import { SessionManager } from '../services/sessionManager.js';
10
11
  import { WorktreeService } from '../services/worktreeService.js';
11
12
  import { shortcutManager } from '../services/shortcutManager.js';
13
+ import { configurationManager } from '../services/configurationManager.js';
12
14
  const App = () => {
13
15
  const { exit } = useApp();
14
16
  const [view, setView] = useState('menu');
@@ -17,6 +19,7 @@ const App = () => {
17
19
  const [activeSession, setActiveSession] = useState(null);
18
20
  const [error, setError] = useState(null);
19
21
  const [menuKey, setMenuKey] = useState(0); // Force menu refresh
22
+ const [selectedWorktree, setSelectedWorktree] = useState(null); // Store selected worktree for preset selection
20
23
  useEffect(() => {
21
24
  // Listen for session exits to return to menu automatically
22
25
  const handleSessionExit = (session) => {
@@ -76,8 +79,15 @@ const App = () => {
76
79
  // Get or create session for this worktree
77
80
  let session = sessionManager.getSession(worktree.path);
78
81
  if (!session) {
82
+ // Check if we should show preset selector
83
+ if (configurationManager.getSelectPresetOnStart()) {
84
+ setSelectedWorktree(worktree);
85
+ setView('preset-selector');
86
+ return;
87
+ }
79
88
  try {
80
- session = await sessionManager.createSession(worktree.path);
89
+ // Use preset-based session creation with default preset
90
+ session = await sessionManager.createSessionWithPreset(worktree.path);
81
91
  }
82
92
  catch (error) {
83
93
  setError(`Failed to create session: ${error}`);
@@ -87,6 +97,27 @@ const App = () => {
87
97
  setActiveSession(session);
88
98
  setView('session');
89
99
  };
100
+ const handlePresetSelected = async (presetId) => {
101
+ if (!selectedWorktree)
102
+ return;
103
+ try {
104
+ // Create session with selected preset
105
+ const session = await sessionManager.createSessionWithPreset(selectedWorktree.path, presetId);
106
+ setActiveSession(session);
107
+ setView('session');
108
+ setSelectedWorktree(null);
109
+ }
110
+ catch (error) {
111
+ setError(`Failed to create session: ${error}`);
112
+ setView('menu');
113
+ setSelectedWorktree(null);
114
+ }
115
+ };
116
+ const handlePresetSelectorCancel = () => {
117
+ setSelectedWorktree(null);
118
+ setView('menu');
119
+ setMenuKey(prev => prev + 1);
120
+ };
90
121
  const handleReturnToMenu = () => {
91
122
  setActiveSession(null);
92
123
  setError(null);
@@ -229,6 +260,9 @@ const App = () => {
229
260
  if (view === 'configuration') {
230
261
  return React.createElement(Configuration, { onComplete: handleReturnToMenu });
231
262
  }
263
+ if (view === 'preset-selector') {
264
+ return (React.createElement(PresetSelector, { onSelect: handlePresetSelected, onCancel: handlePresetSelectorCancel }));
265
+ }
232
266
  return null;
233
267
  };
234
268
  export default App;