Add shortcuts for terminal close and chat with same Git state#56

merged3
main
codething/48203257
openedFeb 16, 2026byJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 12d ago

Summary

  • add new keybinding commands: terminal.close and chat.newSameGitState in shared contracts
  • register default shortcuts for those commands (mod+w for terminal close with terminalFocus, mod+shift+n for new chat with same Git state)
  • wire UI handling so terminal.close closes the active terminal from ChatView
  • update sidebar new-chat flow to optionally preserve branch and worktreePath when using chat.newSameGitState
  • extend docs and tests across server, web, and contracts for the new commands and shortcut behavior

Testing

  • packages/contracts/src/keybindings.test.ts: validates terminal.close is accepted by schema parsing
  • apps/server/src/keybindings.test.ts: verifies default bindings include terminal.close and chat.newSameGitState
  • apps/web/src/keybindings.test.ts: verifies shortcut matching for terminal.close and chat.newSameGitState, including terminalFocus behavior
  • Not run: full project lint/test commands in this environment

Open with Devin

Summary by CodeRabbit

Release Notes

  • New Features

    • Added keyboard shortcut (Mod+W) to close the active terminal.
    • Added keyboard shortcut (Mod+Shift+N) to create a new chat thread with the current branch/worktree state.
    • Terminal and chat actions are now context-aware, responding intelligently based on terminal focus state.
  • UI/UX Improvements

    • Enhanced terminal close action visibility in the terminal drawer with clearer labeling and icon.

Added 1 commit

  • Add shortcuts for terminal close and chat with same Git statefb4afca
Synced from GitHub

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request adds two new keybindings: a terminal close command (mod+w) that works when terminal focus is active, and a local chat thread command (mod+shift+n) that creates new threads while preserving the current git branch and worktree state. The changes update keybinding definitions, add context-aware shortcut detection helpers, and modify UI components to handle and display these new shortcuts.

Changes

Cohort / File(s)Summary
Keybinding Definitions
KEYBINDINGS.md, apps/server/src/keybindings.ts, packages/contracts/src/keybindings.ts
Added terminal.close (mod+w) with terminalFocus condition and chat.newLocal (mod+shift+n) with !terminalFocus condition. Updated terminal and chat command semantics to be gated by focus state. Extended keybinding schema to include new command types.
Keybinding Utilities & Tests
apps/web/src/keybindings.ts, apps/web/src/keybindings.test.ts, packages/contracts/src/keybindings.test.ts
Added isTerminalCloseShortcut() and isChatNewLocalShortcut() helper functions following existing patterns. Extended test coverage to validate new shortcuts across platform-specific key combinations and focus states.
Chat View Component
apps/web/src/components/ChatView.tsx
Added terminal close shortcut handling that verifies an active terminal exists and calls closeTerminal(). Introduced memoized closeShortcutLabel for display via ThreadTerminalDrawer prop. Extended keyboard handler dependencies.
Sidebar Component
apps/web/src/components/Sidebar.tsx
Updated handleNewThread() signature to accept optional branch and worktreePath parameters. Added keyboard handler for isChatNewLocalShortcut that creates new threads while preserving current thread's git state.
Terminal Drawer Component
apps/web/src/components/ThreadTerminalDrawer.tsx
Added closeShortcutLabel prop. Introduced computed closeTerminalActionLabel for consistent labeling. Replaced plain close button (×) with Popover-based control displaying close tooltip with shortcut hint. Updated per-terminal close labels to include shortcut information.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately describes the main changes: adding shortcuts for terminal close (mod+w) and a new chat command that preserves Git state (mod+shift+n for chat.newLocal).
Merge Conflict Detection✅ Passed✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codething/48203257

Comment @coderabbitai help to get the list of available commands and usage tips.

Synced from GitHub

Add mod+w terminal close and gate chat thread creation shortcuts to preserve or clear Git context in server defaults and web UI

Update default keybindings to include terminal.close on mod+w under terminalFocus and add chat.new/chat.newLocal gated by !terminalFocus; wire terminal.close handling and shortcut labels in ChatView and ThreadTerminalDrawer; route chat.new to preserve active thread branch/worktree and chat.newLocal to create a local thread in Sidebar; extend keybinding schema and tests.

📍Where to Start

Start with the updated default bindings in keybindings.ts, then review shortcut handling in ChatView.tsx and thread creation logic in Sidebar.tsx.


Macroscope summarized 9075086.

Synced from GitHub

Greptile Summary

Adds two new keybinding commands (terminal.close and chat.newSameGitState) with default shortcuts (mod+w and mod+shift+n), wires them into the web UI, and updates docs/tests across all three packages.

  • Extends the shared keybindingCommandSchema enum in packages/contracts with the two new commands
  • Registers default bindings in apps/server/src/keybindings.ts — terminal.close is gated by terminalFocus
  • Adds shortcut matcher functions (isTerminalCloseShortcut, isChatNewSameGitStateShortcut) in the web keybindings module
  • ChatView handles terminal.close by closing the active terminal via closeTerminal, with proper dependency array updates
  • Sidebar handles chat.newSameGitState by passing the active thread's branch and worktreePath to handleNewThread
  • KEYBINDINGS.md updated with new commands and defaults
  • Tests added/updated across contracts, server, and web packages
  • Note: mod+w default may conflict with browser tab-close in non-Electron contexts (see inline comment)

Confidence Score: 4/5

  • This PR is safe to merge with minor consideration around the mod+w browser shortcut conflict.
  • The changes follow established patterns consistently across all three packages (contracts, server, web). The terminal close logic is properly guarded by terminalFocus context and the store's closeThreadTerminal handles edge cases (last terminal gracefully resets to default). The new git-state-preserving thread creation is clean and well-integrated. The only concern is the mod+w default potentially conflicting with browser tab-close behavior outside Electron, which is a UX consideration rather than a correctness bug.
  • apps/web/src/components/ChatView.tsx — verify that mod+w shortcut interception works as expected in browser-served mode (not just Electron).

Important Files Changed

FilenameOverview
packages/contracts/src/keybindings.tsAdds terminal.close and chat.newSameGitState to the keybinding command enum. Straightforward schema extension, no issues.
apps/server/src/keybindings.tsAdds default keybinding rules for terminal.close (mod+w with terminalFocus) and chat.newSameGitState (mod+shift+n). Consistent with existing patterns.
apps/web/src/keybindings.tsAdds isTerminalCloseShortcut and isChatNewSameGitStateShortcut helper functions following existing pattern of delegating to matchesCommandShortcut. No issues.
apps/web/src/components/ChatView.tsxWires terminal.close shortcut to close the active terminal. Properly guards with terminalOpen check, adds activeTerminalId and closeTerminal to useEffect deps. Note: mod+w may conflict with browser tab-close behavior in non-Electron contexts.
apps/web/src/components/Sidebar.tsxExtends handleNewThread to accept optional branch/worktreePath. Adds chat.newSameGitState shortcut handler that preserves active thread's git state. Checks isChatNewSameGitStateShortcut before isChatNewShortcut (correct order since they use different keys).
apps/web/src/keybindings.test.tsAdds tests for terminal.close and chat.newSameGitState shortcut matching including terminalFocus context validation. Comprehensive coverage.
apps/server/src/keybindings.test.tsVerifies new default keybinding entries exist for terminal.close and chat.newSameGitState. Clean.
packages/contracts/src/keybindings.test.tsAdds schema parsing test for terminal.close command. Clean extension of existing tests.
KEYBINDINGS.mdDocuments new commands and their default keybindings. Accurate and consistent with code.

Flowchart

mermaid
1flowchart TD
2 subgraph Contracts["packages/contracts"]
3 Schema["keybindingCommandSchema\n+ terminal.close\n+ chat.newSameGitState"]
4 end
5
6 subgraph Server["apps/server"]
7 Defaults["DEFAULT_KEYBINDINGS\nmod+w → terminal.close\nmod+shift+n → chat.newSameGitState"]
8 end
9
10 subgraph Web["apps/web"]
11 Matchers["keybindings.ts\nisTerminalCloseShortcut()\nisChatNewSameGitStateShortcut()"]
12
13 subgraph ChatView["ChatView.tsx"]
14 KDHandler["keydown handler"]
15 CloseCheck{"isTerminalCloseShortcut?"}
16 CloseGuard{"terminalOpen?"}
17 CloseAction["closeTerminal(activeTerminalId)"]
18 end
19
20 subgraph Sidebar["Sidebar.tsx"]
21 SidebarHandler["keydown handler"]
22 GitStateCheck{"isChatNewSameGitStateShortcut?"}
23 NewThread["handleNewThread(projectId,\n{branch, worktreePath})"]
24 end
25 end
26
27 Schema --> Defaults
28 Defaults --> Matchers
29 Matchers --> KDHandler
30 KDHandler --> CloseCheck
31 CloseCheck -->|Yes| CloseGuard
32 CloseGuard -->|Yes| CloseAction
33 Matchers --> SidebarHandler
34 SidebarHandler --> GitStateCheck
35 GitStateCheck -->|Yes| NewThread

Last reviewed commit: fb4afca

apps/server/src/keybindings.tsline 31Outdated · fb4afcaOpen thread
……@@ -28,7 +28,9 @@ export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [
2828 { key: "mod+j", command: "terminal.toggle" },
2929 { key: "mod+d", command: "terminal.split", when: "terminalFocus" },
3030 { key: "mod+n", command: "terminal.new", when: "terminalFocus" },
31+ { key: "mod+w", command: "terminal.close", when: "terminalFocus" },

mod+w conflicts with browser tab-close

Cmd+W / Ctrl+W is the standard shortcut for closing a browser tab. While the terminalFocus guard limits when this fires, most browsers do not allow JavaScript to intercept and preventDefault() on Ctrl+W/Cmd+W — the tab will still close.

This should work fine in Electron (where the app controls key event routing), but in the browser-served mode the shortcut will effectively be unusable and may cause unexpected tab closures. If the app is meant to run in both contexts, consider choosing a different default binding for browser users (e.g. mod+shift+w).

Synced from GitHub
🧹 Nitpick comments (1)
packages/contracts/src/keybindings.test.ts (1)

17-23: Consider adding chat.newSameGitState parsing coverage for parity.

The new command is now part of the schema; adding a matching parse assertion keeps the contract tests symmetrical.

🧪 Suggested test addition
diff
1 const parsedClose = keybindingRuleSchema.parse({
2 key: "mod+w",
3 command: "terminal.close",
4 });
5 assert.strictEqual(parsedClose.command, "terminal.close");
6+
7+ const parsedSameGit = keybindingRuleSchema.parse({
8+ key: "mod+shift+n",
9+ command: "chat.newSameGitState",
10+ });
11+ assert.strictEqual(parsedSameGit.command, "chat.newSameGitState");

Added 2 commits

  • Rename local chat shortcut and surface terminal close hintsbd99acd
  • doc9075086