Every time you open a new chat in Claude Code extension, it automatically attaches your currently-open file as context.
This wastes tokens, can leak sensitive files (like .env), and adds noise to every prompt.
This guide shows you how to turn off that feature.
Based on community fix from:
Important
On extension version 2.1.273 and newer, the upstream removed the include/exclude toggle button.
After this patch there is no chip and no toggle — nothing is auto-attached, so there is nothing to Remove per chat.
To include file context you must add it manually each time: type @ to mention a file, or use + > Upload from computer.
Important
Disable auto-update for the "Claude Code for VS Code" extension, otherwise auto-updates will silently overwrite your patched file.
Go to the Extensions tab (Ctrl+Shift+X / Cmd+Shift+X), find "Claude Code for VS Code", and uncheck Auto Update.
When you want to update:
- Disable "Claude Code for VS Code" extension
- Update to the latest version
- Re-enable the extension
- Restart Extension
- Re-run the script
-
Download or save the fix-auto-attach.ps1 file to your computer.
-
Open PowerShell in the folder where you saved the script and run:
# The -Force parameter skips the user confirmation prompt to speed things up Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force .\fix-auto-attach.ps1
Or apply directly with a one-liner (no script download needed, 2.1.273 only):
$f = (Get-ChildItem "$env:USERPROFILE\.vscode\extensions\anthropic.claude-code-*\webview\index.js" -Recurse | Select-Object -Last 1).FullName; $c = Get-Content $f -Raw; $c = $c -replace 'let (\w+)=!([A-Za-z_\$][\w\$]*);(\w+)\(\$\.selection\.value,\1,', 'let $1=!1;$3($$.selection.value,$1,'; $c = $c -replace 'applySelectionUpdate\(\$\)\{let J=this\.dismissedSelection;', 'applySelectionUpdate($){if($!==void 0)return;let J=this.dismissedSelection;'; Set-Content $f $c -NoNewline
❗ Important: For Cursor replace
\.vscodewith\.cursor, and for VSCodium with\.vscode-oss.Custom path & dry run:
# Preview the patch against a specific bundle without writing anything .\fix-auto-attach.ps1 -Path "C:\path\to\index.js" -DryRun # Apply to a specific bundle (a file, or a directory containing webview\index.js) .\fix-auto-attach.ps1 -Path "C:\path\to\index.js"
-
Reload VS Code / VSCodium / Cursor:
- Press
Ctrl+Shift+P - Type and run: Developer: Reload Window
- Press
Run the fix in one command (2.1.273 only):
WV=$(find ~/.vscode{,-server}/extensions -path '*anthropic.claude-code-*/webview/index.js' 2>/dev/null | tail -1)
cp "$WV" "$WV.bak"
perl -i -pe 's{let (\w+)=!([A-Za-z_\$][\w\$]*);(\w+)\(\$\.selection\.value,\1,}{let $1=!1;$3(\$.selection.value,$1,}g; s/applySelectionUpdate\(\$\)\{let J=this\.dismissedSelection;/applySelectionUpdate(\$){if(\$!==void 0)return;let J=this.dismissedSelection;/g' "$WV"❗ Important: For Cursor replace ~/.vscode with ~/.cursor, and for VSCodium replace with ~/.vscode-oss.
Then press Cmd+Shift+P → Developer: Reload Window.
Caution
🚨 USE AT YOUR OWN RISK! 🚨
If you want to be absolutely certain that files can't be auto-injected – even if you accidentally click the toggle – use Hardcore mode. It removes the injection code entirely. Any remaining chip/toggle UI stays visible but does nothing (2.1.273+ has no toggle — the selection chip is display-only).
PowerShell:
.\fix-auto-attach.ps1 -HardcoreBash:
WV=$(find ~/.vscode{,-server}/extensions -path '*anthropic.claude-code-*/webview/index.js' 2>/dev/null | tail -1)
cp "$WV" "$WV.bak"
perl -0 -i -pe 's{if\(([A-Za-z_\$][\w\$]*)\)if\(\1\.selectedText\)([A-Za-z_\$][\w\$]*)\.push\(\{type:"text",text:`<ide_selection>[\s\S]*?</ide_selection>`\}\);else \2\.push\(\{type:"text",text:`<ide_opened_file>[\s\S]*?</ide_opened_file>`\}\);}{}g' "$WV"❗ Important: For Cursor replace ~/.vscode with ~/.cursor, and for VSCodium replace with ~/.vscode-oss.
Then Developer: Reload Window (Ctrl+Shift+P / Cmd+Shift+P).
Want to undo the patch? Restore the backup and reload:
PowerShell:
Get-ChildItem "$env:USERPROFILE\.vscode\extensions\anthropic.claude-code-*\webview\index.js.bak" | ForEach-Object {
Copy-Item -Path $_.FullName -Destination (Join-Path $_.DirectoryName "index.js") -Force
}❗ Important: For Cursor replace \.vscode with \.cursor, and for VSCodium with \.vscode-oss.
Bash:
WV=$(find ~/.vscode{,-server}/extensions -path '*anthropic.claude-code-*/webview/index.js' 2>/dev/null | tail -1) && cp -f "$WV.bak" "$WV"❗ Important: For Cursor replace ~/.vscode with ~/.cursor, and for VSCodium replace with ~/.vscode-oss.
Then Developer: Reload Window (Ctrl+Shift+P / Cmd+Shift+P).
Note
If the extension auto-updated since you applied the patch, the .bak file may be a version behind and causing errors when the extension runs.
In that case, reinstall the extension to get a fresh index.js, or download the same version manually from Open VSX (under Resources) and copy webview/index.js into the extension's webview/ folder.
In 2.1.273 the upstream removed the includeSelection toggle: every non-slash message auto-attaches the current selection (let w1=!r = !isSlashCommand), and the chip renders from session.selection, which reactive effects keep seeded from the IDE. The patch does two things: forces that send flag to false (let w1=!1) so no selection content is sent, and guards applySelectionUpdate to drop non-undefined seeds so the chip never appears. There is no toggle to turn back ON per chat — use @-mentions or the attach-file button for manual context. (On older versions ≤2.1.267 the patch instead flipped the includeSelection useState(true) default to false, keeping the toggle functional.)
No. The patch only changes a default value. All features remain functional. The only difference: your open file won't be auto-attached to new conversations.
Auto-updates revert the patch because the extension files get replaced. After an update, just run the script again. The script tells you if the pattern wasn't found.
The script tries four patterns — legacy (≤2.1.177, namespace hooks like Ke.useRef), modern (≥2.1.211, direct aliases like Se=useRef), void-0-ref (≥2.1.267, ref alias called with void 0 like =G1(void 0),[L,b]=n(!0),...), and send-flag without toggle (≥2.1.273, let w1=!r;JJ0($.selection.value,w1,...)). If all fail, the extension was updated and the variable names changed.
To debug, unpack the bundle with webcrack:
npx webcrack <path-to-webview>/index.js -o ./unpackedThen search for ide_opened_file in ./unpacked/deobfuscated.js — the function containing it is your injection producer. On ≤2.1.267, look for the React component that calls it; the chip's toggle state is the useState(!0) / ne(!0) / n(!0) (e.g. includeSelection) in that same component. On ≥2.1.273 there is no toggle — find the .send(...) caller that passes the selection flag (e.g. await $.send(z1,W,w1,{kind:"human"})) and trace where that flag is assigned.
Check the original GitHub comment for updates, or file an issue linking back to it.
No. Only the automatic <ide_opened_file> and <ide_selection> injection. Manual attachments still work as expected.
Yes. The PowerShell script automatically searches .vscode, .vscode-server, .vscode-oss, .cursor, and .cursor-server extension directories and picks the most recent bundle.
| Action | Command |
|---|---|
| Apply fix (Windows) | .\fix-auto-attach.ps1 |
| Apply fix (Mac/Linux) | Run the perl one-liner above |
| Apply fix to a custom bundle | .\fix-auto-attach.ps1 -Path "C:\path\to\index.js" |
| Preview without writing (dry run) | .\fix-auto-attach.ps1 -DryRun |
| Hardcore mode (Windows) | .\fix-auto-attach.ps1 -Hardcore |
| Unpack bundle for inspection | npx webcrack <path>/index.js -o ./unpacked |
| Revert | Restore .bak file, reload window |
| Reload window | Ctrl+Shift+P → Developer: Reload Window |
The auto-attach logic lives in a minified React component inside the extension's webview/index.js. There are four bundle formats the script handles (one-liners in this guide target 2.1.273 / Format D only):
Hooks called via a React namespace variable (e.g. Ke.useRef, Ke.useState):
_=Ke.useRef(!0),[v,x]=Ke.useState(!0) // true = ON by defaultThe patch flips the useState default:
_=Ke.useRef(!0),[v,x]=Ke.useState(!1) // false = OFF by defaultThe =Ke.useRef(!0) anchor (with leading =) uniquely identifies this useState among the many useState(!0) calls in the bundle.
Hooks destructured as local aliases (e.g. Se=useRef, ne=useState):
_=Se(!0),[C,y]=ne(!0) // true = ON by defaultPatched:
_=Se(!0),[C,y]=ne(!1) // false = OFF by defaultAgain the leading = anchors to the useRef-alias assignment, making the match unique.
Same direct-alias hooks, but the useRef alias is now called with (void 0) instead of (!0), so Format B no longer matches. The toggle state (includeSelection) is anchored by the trailing state sequence:
_=G1(void 0),[L,b]=n(!0),[f,h]=n(!1),[S,a]=n(null) // true = ON by defaultPatched:
_=G1(void 0),[L,b]=n(!1),[f,h]=n(!1),[S,a]=n(null) // false = OFF by defaultThe script auto-detects which format your bundle uses and applies the correct pattern. On ≤2.1.267 the toggle button remains fully functional — only the default changes.
The includeSelection toggle was removed upstream. The send handler now computes the flag as !isSlashCommand, so every non-slash message auto-attaches the selection:
let w1=!r;JJ0($.selection.value,w1,...),await $.send(z1,W,w1,{kind:"human"})Forcing the flag alone is not enough: the chip renders from session.selection, which reactive effects keep seeded from the IDE via applySelectionUpdate — so the chip would still appear and demand a manual Remove click. The patch therefore does two things:
let w1=!1;JJ0($.selection.value,w1,...),await $.send(z1,W,w1,{kind:"human"})applySelectionUpdate($){if($!==void 0)return;let J=this.dismissedSelection;...}The guard only drops non-undefined seeds; explicit applySelectionUpdate(undefined) calls (clear-on-close, dismiss) and dismissSelection() still run, and manual @-mentions / file upload (separate attachedFiles state) keep working. There is no toggle to flip back ON — standard mode on 2.1.273+ means never auto-attach, no chip shown.
Tested on: Claude Code for VS Code 2.1.273