Instantly share code, notes, and snippets.
Created
April 19, 2026 02:59
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save mikegwhit/3f469c2a8a80b78bb4f052ec694f5ba2 to your computer and use it in GitHub Desktop.
claude-code-vscode-add-file-or-folder-to-context-menu.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const vscode = require('vscode'); | |
| const path = require('path'); | |
| const fs = require('fs'); | |
| /** | |
| * Resolves the Claude Code insertAtMention command name, | |
| * or null if Claude Code isn't installed. | |
| * @return {Promise<string|null>} | |
| */ | |
| async function findClaudeCommand() { | |
| const all = await vscode.commands.getCommands(true); | |
| if (all.includes('claude-vscode.insertAtMention')) { | |
| return 'claude-vscode.insertAtMention'; | |
| } | |
| if (all.includes('claude-code.insertAtMentioned')) { | |
| return 'claude-code.insertAtMentioned'; | |
| } | |
| return null; | |
| } | |
| /** | |
| * Returns a workspace-relative @mention string for a URI. | |
| * @param {vscode.Uri} u | |
| * @return {string} | |
| */ | |
| function toMention(u) { | |
| const folders = vscode.workspace.workspaceFolders; | |
| const wsRoot = folders && folders.length > 0 | |
| ? folders[0].uri.fsPath | |
| : (process.env.HOME || '/tmp'); | |
| const rel = path.relative(wsRoot, u.fsPath); | |
| return '@' + (rel.startsWith('..') ? u.fsPath : rel); | |
| } | |
| /** | |
| * Returns true if the given URI points to a directory. | |
| * @param {vscode.Uri} u | |
| * @return {boolean} | |
| */ | |
| function isDirectory(u) { | |
| try { | |
| return fs.statSync(u.fsPath).isDirectory(); | |
| } catch (_) { | |
| return false; | |
| } | |
| } | |
| /** | |
| * Injects a single file @mention into the Claude Code | |
| * sidebar input using the insertAtMention command (same | |
| * mechanism as Alt+K). Opens the file as the active | |
| * editor so the command can read it. | |
| * @param {vscode.Uri} u | |
| * @param {string} claudeCmd | |
| */ | |
| async function injectFileToClaudeInput(u, claudeCmd) { | |
| await vscode.window.showTextDocument(u, { | |
| preview: true, | |
| preserveFocus: false, | |
| }); | |
| await vscode.commands.executeCommand(claudeCmd); | |
| } | |
| /** | |
| * Injects a folder @mention into the Claude Code sidebar | |
| * input using the same insertAtMention mechanism as files. | |
| * | |
| * Trick: open an untitled document whose URI path equals | |
| * the folder's fsPath. insertAtMention reads | |
| * document.fileName → workspace.asRelativePath() → fires | |
| * @relativeFolder into Claude Code. We close the scratch | |
| * document immediately after. | |
| * | |
| * Falls back to clipboard + sidebar focus if that fails. | |
| * | |
| * @param {vscode.Uri} u | |
| * @param {string} claudeCmd | |
| */ | |
| async function injectFolderToClaudeInput(u, claudeCmd) { | |
| try { | |
| const scratchUri = vscode.Uri.parse( | |
| 'untitled:' + u.fsPath); | |
| const doc = await vscode.workspace | |
| .openTextDocument(scratchUri); | |
| await vscode.window.showTextDocument(doc, { | |
| preview: true, | |
| preserveFocus: false, | |
| }); | |
| await vscode.commands.executeCommand(claudeCmd); | |
| await vscode.commands.executeCommand( | |
| 'workbench.action.closeActiveEditor'); | |
| return; | |
| } catch (_) {} | |
| // Fallback: clipboard + focus sidebar. | |
| const mention = toMention(u); | |
| await vscode.env.clipboard.writeText(mention); | |
| for (const cmd of [ | |
| 'claudeVSCodeSidebarSecondary.focus', | |
| 'claudeVSCodeSidebar.focus', | |
| ]) { | |
| try { | |
| await vscode.commands.executeCommand(cmd); | |
| break; | |
| } catch (_) {} | |
| } | |
| vscode.window.showInformationMessage( | |
| `${mention} copied — press Ctrl+V to add to Claude`); | |
| } | |
| /** | |
| * "Add to Claude Context" command handler. | |
| * | |
| * - Files → opens as active editor + fires insertAtMention | |
| * (identical to Alt+K, injects into sidebar input) | |
| * - Folders → sends @folderPath to Claude terminal, or clipboard | |
| * - Multi-select in Explorer passes all URIs as second arg. | |
| * | |
| * @param {vscode.Uri|undefined} uri | |
| * @param {vscode.Uri[]|undefined} uris | |
| */ | |
| async function addToClaudeContext(uri, uris) { | |
| let targets = []; | |
| if (uris && uris.length > 0) { | |
| targets = uris; | |
| } else if (uri) { | |
| targets = [uri]; | |
| } else { | |
| const editor = vscode.window.activeTextEditor; | |
| if (editor) targets = [editor.document.uri]; | |
| } | |
| if (targets.length === 0) { | |
| vscode.window.showWarningMessage( | |
| 'Claude Context: no file or folder selected.'); | |
| return; | |
| } | |
| const claudeCmd = await findClaudeCommand(); | |
| if (!claudeCmd) { | |
| // Claude Code not installed — clipboard fallback for all. | |
| const text = targets.map(toMention).join(' '); | |
| await vscode.env.clipboard.writeText(text); | |
| vscode.window.showInformationMessage( | |
| `Claude Code not found — copied to clipboard: ${text}`); | |
| return; | |
| } | |
| for (const u of targets) { | |
| if (isDirectory(u)) { | |
| await injectFolderToClaudeInput(u, claudeCmd); | |
| } else { | |
| await injectFileToClaudeInput(u, claudeCmd); | |
| } | |
| } | |
| } | |
| module.exports = {addToClaudeContext}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment