feat: implement worktree session creation and management

- Added `createWorktreeSession` utility to handle the creation of new sessions with auto-generated worktrees.
- Introduced branch name generation utilities for creating unique and friendly branch names.
- Updated `CommandPalette` to trigger worktree session creation via a command.
- Refactored keyboard shortcuts to support new worktree session creation with Shift + Cmd/Ctrl + N.
- Enhanced project settings to include worktree defaults (branch prefix, base branch, auto-create option).
- Updated persistence logic to preserve worktree defaults when saving project settings.
- Modified menu actions to initiate new worktree sessions.
- Ensured proper handling of existing branches to avoid conflicts during worktree creation.
This commit is contained in:
Bohdan Triapitsyn
2026-01-07 22:06:28 +02:00
parent 4f6eea9ea5
commit d92a1ab297
14 changed files with 1004 additions and 883 deletions
@@ -5,6 +5,7 @@ import { useThemeSystem } from '@/contexts/useThemeSystem';
import { useAssistantStatus } from '@/hooks/useAssistantStatus';
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
import { hasModifier } from '@/lib/utils';
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
export const useKeyboardShortcuts = () => {
const { openNewSessionDraft, abortCurrentOperation, armAbortPrompt, clearAbortPrompt, currentSessionId } = useSessionStore();
@@ -13,7 +14,6 @@ export const useKeyboardShortcuts = () => {
toggleHelpDialog,
toggleSidebar,
setSessionSwitcherOpen,
setSessionCreateDialogOpen,
setActiveMainTab,
setSettingsDialogOpen,
setModelSelectorOpen,
@@ -82,10 +82,13 @@ export const useKeyboardShortcuts = () => {
if (hasModifier(e) && e.key.toLowerCase() === 'n') {
e.preventDefault();
if (e.shiftKey) {
setSessionCreateDialogOpen(true);
// Shift+Cmd/Ctrl+N creates a new session with auto-generated worktree
setActiveMainTab('chat');
setSessionSwitcherOpen(false);
createWorktreeSession();
return;
}
// Cmd/Ctrl+N opens a new session without worktree
setActiveMainTab('chat');
setSessionSwitcherOpen(false);
openNewSessionDraft();
@@ -138,7 +141,6 @@ export const useKeyboardShortcuts = () => {
isCommandPaletteOpen,
isHelpDialogOpen,
isSessionSwitcherOpen,
isSessionCreateDialogOpen,
isAboutDialogOpen,
activeMainTab,
isModelSelectorOpen,
@@ -150,7 +152,7 @@ export const useKeyboardShortcuts = () => {
}
// Skip if any overlay open or not on chat tab
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isSessionCreateDialogOpen || isAboutDialogOpen;
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
const isChatActive = activeMainTab === 'chat';
if (hasOverlay || !isChatActive) {
@@ -168,7 +170,6 @@ export const useKeyboardShortcuts = () => {
isCommandPaletteOpen,
isHelpDialogOpen,
isSessionSwitcherOpen,
isSessionCreateDialogOpen,
isAboutDialogOpen,
activeMainTab,
} = useUIStore.getState();
@@ -182,7 +183,7 @@ export const useKeyboardShortcuts = () => {
}
// Check if any overlay is open or not on chat tab - don't process abort
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isSessionCreateDialogOpen || isAboutDialogOpen;
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
const isChatActive = activeMainTab === 'chat';
if (hasOverlay || !isChatActive) {
@@ -238,7 +239,6 @@ export const useKeyboardShortcuts = () => {
toggleHelpDialog,
toggleSidebar,
setSessionSwitcherOpen,
setSessionCreateDialogOpen,
setActiveMainTab,
setSettingsDialogOpen,
setModelSelectorOpen,
+6 -5
View File
@@ -8,6 +8,7 @@ import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
import { sessionEvents } from '@/lib/sessionEvents';
import { isDesktopRuntime } from '@/lib/desktop';
import { useFileSystemAccess } from '@/hooks/useFileSystemAccess';
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
const MENU_ACTION_EVENT = 'openchamber:menu-action';
@@ -16,7 +17,7 @@ type MenuAction =
| 'settings'
| 'command-palette'
| 'new-session'
| 'worktree-creator'
| 'new-worktree-session'
| 'change-workspace'
| 'open-git-tab'
| 'open-diff-tab'
@@ -38,7 +39,6 @@ export const useMenuActions = (
toggleHelpDialog,
toggleSidebar,
setSessionSwitcherOpen,
setSessionCreateDialogOpen,
setActiveMainTab,
setSettingsDialogOpen,
setAboutDialogOpen,
@@ -108,8 +108,10 @@ export const useMenuActions = (
openNewSessionDraft();
break;
case 'worktree-creator':
setSessionCreateDialogOpen(true);
case 'new-worktree-session':
setActiveMainTab('chat');
setSessionSwitcherOpen(false);
createWorktreeSession();
break;
case 'change-workspace':
@@ -202,7 +204,6 @@ export const useMenuActions = (
toggleHelpDialog,
toggleSidebar,
setSessionSwitcherOpen,
setSessionCreateDialogOpen,
setActiveMainTab,
setSettingsDialogOpen,
setAboutDialogOpen,