@@ -20,6 +20,8 @@ import type { ITerminal, ITab } from '@/stores'
2020import { useTasks } from '@/hooks/use-tasks'
2121import { useRepositories } from '@/hooks/use-repositories'
2222import { useWorktreeBasePath } from '@/hooks/use-config'
23+ import { useTerminalViewState } from '@/hooks/use-terminal-view-state'
24+ import { useHotkeys } from '@/hooks/use-hotkeys'
2325import { cn } from '@/lib/utils'
2426import type { Terminal as XTerm } from '@xterm/xterm'
2527import type { TerminalTab , TaskStatus } from '@/types'
@@ -95,6 +97,9 @@ const TerminalsView = observer(function TerminalsView() {
9597 // State for tab edit dialog
9698 const [ editingTab , setEditingTab ] = useState < TerminalTab | null > ( null )
9799
100+ // View state for tracking focused terminals
101+ const { getFocusedTerminal } = useTerminalViewState ( )
102+
98103 // URL is the source of truth for active tab
99104 // Fall back to first tab if URL doesn't specify a valid tab
100105 const tabIds = useMemo ( ( ) => tabs . map ( ( t ) => t . id ) , [ tabs ] )
@@ -538,6 +543,26 @@ const TerminalsView = observer(function TerminalsView() {
538543 [ updateTab ]
539544 )
540545
546+ // Keyboard shortcuts (Cmd+D/W only work on desktop - browser intercepts on web)
547+ useHotkeys ( 'meta+d' , handleTerminalAdd , {
548+ enabled : activeTabId !== ALL_TASKS_TAB_ID && connected ,
549+ allowInTerminal : true ,
550+ deps : [ handleTerminalAdd , activeTabId , connected ] ,
551+ } )
552+
553+ useHotkeys ( 'meta+w' , ( ) => {
554+ if ( activeTabId && activeTabId !== ALL_TASKS_TAB_ID ) {
555+ const focusedId = getFocusedTerminal ( activeTabId )
556+ if ( focusedId ) {
557+ handleTerminalClose ( focusedId )
558+ }
559+ }
560+ } , {
561+ enabled : activeTabId !== ALL_TASKS_TAB_ID ,
562+ allowInTerminal : true ,
563+ deps : [ activeTabId , getFocusedTerminal , handleTerminalClose ] ,
564+ } )
565+
541566 return (
542567 < div className = "flex h-full max-w-full flex-col overflow-hidden" >
543568 { /* Tab Bar + Actions */ }
0 commit comments