diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index 0a8a71e781fb..f8b1ea94c332 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -4860,6 +4860,13 @@ function ChatViewContent(props: ChatViewProps) { return; } + if (command === "rightPanel.openTerminal") { + event.preventDefault(); + event.stopPropagation(); + addTerminalSurface(); + return; + } + if (command === "terminal.split") { event.preventDefault(); event.stopPropagation(); diff --git a/docs/user/keybindings.md b/docs/user/keybindings.md index 8e56a79a287d..2bb2db02a43f 100644 --- a/docs/user/keybindings.md +++ b/docs/user/keybindings.md @@ -52,6 +52,9 @@ successful pick; its hover glow and badge preview the element and color family t `rightPanel.toggleMaximized` maximizes or restores the open right panel. It has no default shortcut, so add one in **Settings** → **Keybindings** if you want to use it. +`rightPanel.openTerminal` opens a terminal as a right-panel surface for the active thread, +independent of the bottom drawer, and defaults to `mod+alt+j`. + The command palette searches active thread titles, projects, branches, user messages, and final agent responses across connected environments. Message matches show one labeled excerpt while keeping the thread's project, branch, and machine context visible. Message search begins after two diff --git a/packages/contracts/src/keybindings.ts b/packages/contracts/src/keybindings.ts index 19276c41e7b6..372106a525d4 100644 --- a/packages/contracts/src/keybindings.ts +++ b/packages/contracts/src/keybindings.ts @@ -56,6 +56,7 @@ export const STATIC_KEYBINDING_COMMANDS = [ "terminal.close", "rightPanel.toggle", "rightPanel.toggleMaximized", + "rightPanel.openTerminal", "diff.toggle", "preview.toggle", "preview.refresh", diff --git a/packages/shared/src/keybindings.test.ts b/packages/shared/src/keybindings.test.ts new file mode 100644 index 000000000000..95ecc4931c3c --- /dev/null +++ b/packages/shared/src/keybindings.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { DEFAULT_KEYBINDINGS, DEFAULT_RESOLVED_KEYBINDINGS } from "./keybindings.ts"; + +describe("DEFAULT_KEYBINDINGS", () => { + it("binds mod+alt+j to rightPanel.openTerminal", () => { + const rules = DEFAULT_KEYBINDINGS.filter((rule) => rule.command === "rightPanel.openTerminal"); + expect(rules).toEqual([{ key: "mod+alt+j", command: "rightPanel.openTerminal" }]); + }); + + it("resolves the rightPanel.openTerminal default binding", () => { + const binding = DEFAULT_RESOLVED_KEYBINDINGS.find( + (rule) => rule.command === "rightPanel.openTerminal", + ); + expect(binding?.shortcut).toEqual({ + key: "j", + metaKey: false, + ctrlKey: false, + shiftKey: false, + altKey: true, + modKey: true, + }); + }); +}); diff --git a/packages/shared/src/keybindings.ts b/packages/shared/src/keybindings.ts index 158a9ffb1ac9..a8e8e6d3bd73 100644 --- a/packages/shared/src/keybindings.ts +++ b/packages/shared/src/keybindings.ts @@ -22,6 +22,7 @@ export const DEFAULT_KEYBINDINGS: ReadonlyArray = [ { key: "mod+b", command: "sidebar.toggle" }, { key: "mod+j", command: "terminal.toggle" }, { key: "mod+alt+b", command: "rightPanel.toggle" }, + { key: "mod+alt+j", command: "rightPanel.openTerminal" }, { key: "mod+d", command: "terminal.split", when: "terminalFocus" }, { key: "mod+shift+d", command: "terminal.splitVertical", when: "terminalFocus" }, { key: "mod+n", command: "terminal.new", when: "terminalFocus" },