diff --git a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx
index 459e2ce8..c8f33fc0 100644
--- a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx
+++ b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx
@@ -26,6 +26,7 @@ import {
RefreshCw,
Copy,
ScrollText,
+ Terminal,
} from 'lucide-react';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';
@@ -51,6 +52,7 @@ interface WorktreeActionsDropdownProps {
onPull: (worktree: WorktreeInfo) => void;
onPush: (worktree: WorktreeInfo) => void;
onOpenInEditor: (worktree: WorktreeInfo, editorCommand?: string) => void;
+ onOpenInTerminal: (worktree: WorktreeInfo) => void;
onCommit: (worktree: WorktreeInfo) => void;
onCreatePR: (worktree: WorktreeInfo) => void;
onAddressPRComments: (worktree: WorktreeInfo, prInfo: PRInfo) => void;
@@ -81,6 +83,7 @@ export function WorktreeActionsDropdown({
onPull,
onPush,
onOpenInEditor,
+ onOpenInTerminal,
onCommit,
onCreatePR,
onAddressPRComments,
@@ -303,6 +306,10 @@ export function WorktreeActionsDropdown({
)}
+ onOpenInTerminal(worktree)} className="text-xs">
+
+ Open in Terminal
+
{!worktree.isMain && hasInitScript && (
onRunInitScript(worktree)} className="text-xs">
diff --git a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx
index 212e6d89..359a8f99 100644
--- a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx
+++ b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx
@@ -38,6 +38,7 @@ interface WorktreeTabProps {
onPull: (worktree: WorktreeInfo) => void;
onPush: (worktree: WorktreeInfo) => void;
onOpenInEditor: (worktree: WorktreeInfo, editorCommand?: string) => void;
+ onOpenInTerminal: (worktree: WorktreeInfo) => void;
onCommit: (worktree: WorktreeInfo) => void;
onCreatePR: (worktree: WorktreeInfo) => void;
onAddressPRComments: (worktree: WorktreeInfo, prInfo: PRInfo) => void;
@@ -82,6 +83,7 @@ export function WorktreeTab({
onPull,
onPush,
onOpenInEditor,
+ onOpenInTerminal,
onCommit,
onCreatePR,
onAddressPRComments,
@@ -343,6 +345,7 @@ export function WorktreeTab({
onPull={onPull}
onPush={onPush}
onOpenInEditor={onOpenInEditor}
+ onOpenInTerminal={onOpenInTerminal}
onCommit={onCommit}
onCreatePR={onCreatePR}
onAddressPRComments={onAddressPRComments}
diff --git a/apps/ui/src/components/views/board-view/worktree-panel/hooks/use-worktree-actions.ts b/apps/ui/src/components/views/board-view/worktree-panel/hooks/use-worktree-actions.ts
index f1f245dc..d3b1db85 100644
--- a/apps/ui/src/components/views/board-view/worktree-panel/hooks/use-worktree-actions.ts
+++ b/apps/ui/src/components/views/board-view/worktree-panel/hooks/use-worktree-actions.ts
@@ -143,6 +143,24 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
}
}, []);
+ const handleOpenInTerminal = useCallback(async (worktree: WorktreeInfo) => {
+ try {
+ const api = getElectronAPI();
+ if (!api?.worktree?.openInTerminal) {
+ logger.warn('Open in terminal API not available');
+ return;
+ }
+ const result = await api.worktree.openInTerminal(worktree.path);
+ if (result.success && result.result) {
+ toast.success(result.result.message);
+ } else if (result.error) {
+ toast.error(result.error);
+ }
+ } catch (error) {
+ logger.error('Open in terminal failed:', error);
+ }
+ }, []);
+
return {
isPulling,
isPushing,
@@ -153,5 +171,6 @@ export function useWorktreeActions({ fetchWorktrees, fetchBranches }: UseWorktre
handlePull,
handlePush,
handleOpenInEditor,
+ handleOpenInTerminal,
};
}
diff --git a/apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx b/apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx
index fbd54d73..dd8c9376 100644
--- a/apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx
+++ b/apps/ui/src/components/views/board-view/worktree-panel/worktree-panel.tsx
@@ -80,6 +80,7 @@ export function WorktreePanel({
handlePull,
handlePush,
handleOpenInEditor,
+ handleOpenInTerminal,
} = useWorktreeActions({
fetchWorktrees,
fetchBranches,
@@ -246,6 +247,7 @@ export function WorktreePanel({
onPull={handlePull}
onPush={handlePush}
onOpenInEditor={handleOpenInEditor}
+ onOpenInTerminal={handleOpenInTerminal}
onCommit={onCommit}
onCreatePR={onCreatePR}
onAddressPRComments={onAddressPRComments}
@@ -333,6 +335,7 @@ export function WorktreePanel({
onPull={handlePull}
onPush={handlePush}
onOpenInEditor={handleOpenInEditor}
+ onOpenInTerminal={handleOpenInTerminal}
onCommit={onCommit}
onCreatePR={onCreatePR}
onAddressPRComments={onAddressPRComments}
@@ -391,6 +394,7 @@ export function WorktreePanel({
onPull={handlePull}
onPush={handlePush}
onOpenInEditor={handleOpenInEditor}
+ onOpenInTerminal={handleOpenInTerminal}
onCommit={onCommit}
onCreatePR={onCreatePR}
onAddressPRComments={onAddressPRComments}
diff --git a/apps/ui/src/lib/http-api-client.ts b/apps/ui/src/lib/http-api-client.ts
index 2943f3e2..f1d02e9a 100644
--- a/apps/ui/src/lib/http-api-client.ts
+++ b/apps/ui/src/lib/http-api-client.ts
@@ -1805,6 +1805,8 @@ export class HttpApiClient implements ElectronAPI {
this.post('/api/worktree/switch-branch', { worktreePath, branchName }),
openInEditor: (worktreePath: string, editorCommand?: string) =>
this.post('/api/worktree/open-in-editor', { worktreePath, editorCommand }),
+ openInTerminal: (worktreePath: string) =>
+ this.post('/api/worktree/open-in-terminal', { worktreePath }),
getDefaultEditor: () => this.get('/api/worktree/default-editor'),
getAvailableEditors: () => this.get('/api/worktree/available-editors'),
refreshEditors: () => this.post('/api/worktree/refresh-editors', {}),