summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-07-27 15:54:45 -0400
committerFrank <[email protected]>2025-07-27 15:54:45 -0400
commita07d149e28ab8ece54296f5c707b1d2396b3c7ed (patch)
tree01439c35dca2f3b29b01cf94ac0951fd3eb2d3a6
parent3eb982c8cd5a593f1649d49bd90eab4ae7fecd3f (diff)
downloadopencode-a07d149e28ab8ece54296f5c707b1d2396b3c7ed.tar.gz
opencode-a07d149e28ab8ece54296f5c707b1d2396b3c7ed.zip
vscode: add cmd+shift+esc keybinding
-rw-r--r--packages/web/src/content/docs/docs/ide.mdx3
-rw-r--r--sdks/vscode/README.md11
-rw-r--r--sdks/vscode/package.json20
-rw-r--r--sdks/vscode/src/extension.ts120
4 files changed, 89 insertions, 65 deletions
diff --git a/packages/web/src/content/docs/docs/ide.mdx b/packages/web/src/content/docs/docs/ide.mdx
index fd8e0bfe5..b2f7d1e10 100644
--- a/packages/web/src/content/docs/docs/ide.mdx
+++ b/packages/web/src/content/docs/docs/ide.mdx
@@ -9,7 +9,8 @@ opencode integrates with VS Code, Cursor, or any IDE that supports a terminal. J
## Usage
-- **Quick Launch**: Open opencode with `Cmd+Esc` (Mac) or `Ctrl+Esc` (Windows/Linux), or click the opencode button in the UI.
+- **Quick Launch**: Use `Cmd+Esc` (Mac) or `Ctrl+Esc` (Windows/Linux) to open opencode in a split terminal view, or focus an existing terminal session if one is already running.
+- **New Session**: Use `Cmd+Shift+Esc` (Mac) or `Ctrl+Shift+Esc` (Windows/Linux) to start a new opencode terminal session, even if one is already open. You can also click the opencode button in the UI.
- **Context Awareness**: Automatically share your current selection or tab with opencode.
- **File Reference Shortcuts**: Use `Cmd+Option+K` (Mac) or `Alt+Ctrl+K` (Linux/Windows) to insert file references. For example, `@File#L37-42`.
diff --git a/sdks/vscode/README.md b/sdks/vscode/README.md
index 78685b2c7..1ca5078ce 100644
--- a/sdks/vscode/README.md
+++ b/sdks/vscode/README.md
@@ -1,16 +1,17 @@
# opencode VS Code Extension
-A VS Code extension that integrates [opencode](https://opencode.ai) directly into your development environment.
+A Visual Studio Code extension that integrates [opencode](https://opencode.ai) directly into your development workflow.
## Prerequisites
-This extension requires [opencode](https://opencode.ai) to be installed on your system. Visit [opencode.ai](https://opencode.ai) for installation instructions.
+This extension requires the [opencode CLI](https://opencode.ai) to be installed on your system. Visit [opencode.ai](https://opencode.ai) for installation instructions.
## Features
-- **Cmd+Escape**: Launch opencode in a split terminal view
-- **Alt+Cmd+K**: Send selected code to opencode's prompt
-- **Tab awareness**: opencode automatically detects which files you have open
+- **Quick Launch**: Use `Cmd+Esc` (Mac) or `Ctrl+Esc` (Windows/Linux) to open opencode in a split terminal view, or focus an existing terminal session if one is already running.
+- **New Session**: Use `Cmd+Shift+Esc` (Mac) or `Ctrl+Shift+Esc` (Windows/Linux) to start a new opencode terminal session, even if one is already open. You can also click the opencode button in the UI.
+- **Context Awareness**: Automatically share your current selection or tab with opencode.
+- **File Reference Shortcuts**: Use `Cmd+Option+K` (Mac) or `Alt+Ctrl+K` (Linux/Windows) to insert file references. For example, `@File#L37-42`.
## Support
diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json
index 4f2aa1ed2..b42723729 100644
--- a/sdks/vscode/package.json
+++ b/sdks/vscode/package.json
@@ -26,7 +26,15 @@
"commands": [
{
"command": "opencode.openTerminal",
- "title": "Open Terminal with Opencode",
+ "title": "Open opencode",
+ "icon": {
+ "light": "images/button-dark.svg",
+ "dark": "images/button-light.svg"
+ }
+ },
+ {
+ "command": "opencode.openNewTerminal",
+ "title": "Open opencode in new tab",
"icon": {
"light": "images/button-dark.svg",
"dark": "images/button-light.svg"
@@ -40,7 +48,7 @@
"menus": {
"editor/title": [
{
- "command": "opencode.openTerminal",
+ "command": "opencode.openNewTerminal",
"group": "navigation"
}
]
@@ -55,6 +63,14 @@
"linux": "ctrl+escape"
},
{
+ "command": "opencode.openNewTerminal",
+ "title": "Run opencode",
+ "key": "cmd+shift+escape",
+ "mac": "cmd+shift+escape",
+ "win": "ctrl+shift+escape",
+ "linux": "ctrl+shift+escape"
+ },
+ {
"command": "opencode.addFilepathToTerminal",
"title": "opencode: Insert At-Mentioned",
"key": "cmd+alt+k",
diff --git a/sdks/vscode/src/extension.ts b/sdks/vscode/src/extension.ts
index fa6e5c55f..34ec8c64e 100644
--- a/sdks/vscode/src/extension.ts
+++ b/sdks/vscode/src/extension.ts
@@ -3,10 +3,13 @@ export function deactivate() {}
import * as vscode from "vscode"
+const TERMINAL_NAME = "opencode"
+
export function activate(context: vscode.ExtensionContext) {
- const TERMINAL_NAME = "opencode"
+ let openNewTerminalDisposable = vscode.commands.registerCommand("opencode.openNewTerminal", async () => {
+ await openTerminal()
+ })
- // Register command to open terminal in split screen and run opencode
let openTerminalDisposable = vscode.commands.registerCommand("opencode.openTerminal", async () => {
// An opencode terminal already exists => focus it
const existingTerminal = vscode.window.terminals.find((t) => t.name === TERMINAL_NAME)
@@ -15,6 +18,27 @@ export function activate(context: vscode.ExtensionContext) {
return
}
+ await openTerminal()
+ })
+
+ let addFilepathDisposable = vscode.commands.registerCommand("opencode.addFilepathToTerminal", async () => {
+ const fileRef = getActiveFile()
+ if (!fileRef) return
+
+ const terminal = vscode.window.activeTerminal
+ if (!terminal) return
+
+ if (terminal.name === TERMINAL_NAME) {
+ // @ts-ignore
+ const port = terminal.creationOptions.env?.["_EXTENSION_OPENCODE_PORT"]
+ port ? await appendPrompt(parseInt(port), fileRef) : terminal.sendText(fileRef)
+ terminal.show()
+ }
+ })
+
+ context.subscriptions.push(openTerminalDisposable, addFilepathDisposable)
+
+ async function openTerminal() {
// Create a new terminal in split screen
const port = Math.floor(Math.random() * (65535 - 16384 + 1)) + 16384
const terminal = vscode.window.createTerminal({
@@ -57,64 +81,46 @@ export function activate(context: vscode.ExtensionContext) {
await appendPrompt(port, `In ${fileRef}`)
terminal.show()
}
- })
-
- // Register command to add filepath to terminal
- let addFilepathDisposable = vscode.commands.registerCommand("opencode.addFilepathToTerminal", async () => {
- const fileRef = getActiveFile()
- if (!fileRef) return
+ }
- const terminal = vscode.window.activeTerminal
- if (!terminal) return
+ async function appendPrompt(port: number, text: string) {
+ await fetch(`http://localhost:${port}/tui/append-prompt`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ text }),
+ })
+ }
- if (terminal.name === TERMINAL_NAME) {
- // @ts-ignore
- const port = terminal.creationOptions.env?.["_EXTENSION_OPENCODE_PORT"]
- port ? await appendPrompt(parseInt(port), fileRef) : terminal.sendText(fileRef)
- terminal.show()
+ function getActiveFile() {
+ const activeEditor = vscode.window.activeTextEditor
+ if (!activeEditor) return
+
+ const document = activeEditor.document
+ const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri)
+ if (!workspaceFolder) return
+
+ // Get the relative path from workspace root
+ const relativePath = vscode.workspace.asRelativePath(document.uri)
+ let filepathWithAt = `@${relativePath}`
+
+ // Check if there's a selection and add line numbers
+ const selection = activeEditor.selection
+ if (!selection.isEmpty) {
+ // Convert to 1-based line numbers
+ const startLine = selection.start.line + 1
+ const endLine = selection.end.line + 1
+
+ if (startLine === endLine) {
+ // Single line selection
+ filepathWithAt += `#L${startLine}`
+ } else {
+ // Multi-line selection
+ filepathWithAt += `#L${startLine}-${endLine}`
+ }
}
- })
-
- context.subscriptions.push(openTerminalDisposable, addFilepathDisposable)
-}
-async function appendPrompt(port: number, text: string) {
- await fetch(`http://localhost:${port}/tui/append-prompt`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify({ text }),
- })
-}
-
-function getActiveFile() {
- const activeEditor = vscode.window.activeTextEditor
- if (!activeEditor) return
-
- const document = activeEditor.document
- const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri)
- if (!workspaceFolder) return
-
- // Get the relative path from workspace root
- const relativePath = vscode.workspace.asRelativePath(document.uri)
- let filepathWithAt = `@${relativePath}`
-
- // Check if there's a selection and add line numbers
- const selection = activeEditor.selection
- if (!selection.isEmpty) {
- // Convert to 1-based line numbers
- const startLine = selection.start.line + 1
- const endLine = selection.end.line + 1
-
- if (startLine === endLine) {
- // Single line selection
- filepathWithAt += `#L${startLine}`
- } else {
- // Multi-line selection
- filepathWithAt += `#L${startLine}-${endLine}`
- }
+ return filepathWithAt
}
-
- return filepathWithAt
}