Skip to content

Instantly share code, notes, and snippets.

@sekedus
Last active August 15, 2026 09:26
Show Gist options
  • Select an option

  • Save sekedus/fd4e2810db5231aa9b788b33b82eb74f to your computer and use it in GitHub Desktop.

Select an option

Save sekedus/fd4e2810db5231aa9b788b33b82eb74f to your computer and use it in GitHub Desktop.
Stop Claude Code Extension from Auto-Attaching Your Open Files (VS Code, VSCodium, Cursor).

Claude Code Extension: Fix Auto-Attach

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:


🔧 Option 1: Run the Script (Recommended)

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:

  1. Disable "Claude Code for VS Code" extension
  2. Update to the latest version
  3. Re-enable the extension
  4. Restart Extension
  5. Re-run the script

Windows (PowerShell)

  1. Download or save the script to a file, e.g. fix-auto-attach.ps1.

  2. 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). The script auto-detects your bundle format (legacy ≤2.1.177 vs modern ≥2.1.211), but for the one-liner use:

    $f = (Get-ChildItem "$env:USERPROFILE\.vscode\extensions\anthropic.claude-code-*\webview\index.js" -Recurse | Select-Object -Last 1).FullName; $c = Get-Content $f -Raw; if ($c -match '=(\w+)\.useRef\(!0\),\[(\w+),(\w+)\]=(\w+)\.useState\(!0\)') { $c = $c -replace '=(\w+)\.useRef\(!0\),\[(\w+),(\w+)\]=(\w+)\.useState\(!0\)', '=$1.useRef(!0),[$2,$3]=$4.useState(!1)' } else { $c = $c -replace '=(\w+)\(!0\),\[(\w+),(\w+)\]=(\w+)\(!0\)', '=$1(!0),[$2,$3]=$4(!1)' }; Set-Content $f $c -NoNewline

    Important: For Cursor replace \.vscode with \.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"
  3. Reload VS Code / VSCodium / Cursor:

    • Press Ctrl+Shift+P
    • Type and run: Developer: Reload Window

macOS / Linux (bash)

Run the fix in one command (auto-detects legacy ≤2.1.177 vs modern ≥2.1.211 format):

WV=$(find ~/.vscode{,-server}/extensions -path '*anthropic.claude-code-*/webview/index.js' 2>/dev/null | tail -1)
cp "$WV" "$WV.bak"
perl -i -pe 'if(s{useRef\(!0\),\[(\w+),(\w+)\]=(\w+)\.useState\(!0\)}{useRef(!0),[$1,$2]=$3.useState(!1)}){}else{s{=(\w+)\(!0\),\[(\w+),(\w+)\]=(\w+)\(!0\)}{=$1(!0),[$2,$3]=$4(!1)}}' "$WV"

Important: For Cursor replace ~/.vscode with ~/.cursor, and for VSCodium replace with ~/.vscode-oss.

Then press Cmd+Shift+PDeveloper: Reload Window.


🛠️ Option 2: Hardcore Mode

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. The toggle button remains visible but does nothing.

PowerShell:

.\fix-auto-attach.ps1 -Hardcore

Bash:

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).


↩️ How to Revert

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.


❓ FAQ

What does the patch actually do?

The Claude Code webview uses React state (useState(true)) to decide whether to inject the open file. The patch flips the default to useState(false). That's it. The toggle button still works – you can turn attachment ON for individual chats when you want it.

Will this break Claude Code?

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.

What if the extension auto-updates?

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.

I get "Patch pattern not found" – what now?

The script tries two patterns — legacy (≤2.1.177, namespace hooks like Ke.useRef) and modern (≥2.1.211, direct aliases like Se=useRef). If both 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 ./unpacked

Then search for ide_opened_file in ./unpacked/deobfuscated.js — the function containing it is your injection producer. Look for the React component that calls it; the chip's useState(!0) / ne(!0) is in that same component.

Check the original GitHub comment for updates, or file an issue linking back to it.

Does this affect @-mention attachments, images, or drag-drop?

No. Only the automatic <ide_opened_file> and <ide_selection> injection. Manual attachments still work as expected.

I use Cursor or VSCodium – will the script find it?

Yes. The PowerShell script automatically searches .vscode, .vscode-server, .vscode-oss, .cursor, and .cursor-server extension directories and picks the most recent bundle.


📋 Quick Reference

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+PDeveloper: Reload Window

How It Works (for the curious)

The auto-attach chip state lives in a minified React component inside the extension's webview/index.js. There are two bundle formats the script handles:

Format A — Legacy namespace hooks (≤2.1.177)

Hooks called via a React namespace variable (e.g. Ke.useRef, Ke.useState):

_=Ke.useRef(!0),[v,x]=Ke.useState(!0)  // true = ON by default

The patch flips the useState default:

_=Ke.useRef(!0),[v,x]=Ke.useState(!1)  // false = OFF by default

The =Ke.useRef(!0) anchor (with leading =) uniquely identifies this useState among the many useState(!0) calls in the bundle.

Format B — Direct hook imports (≥2.1.211)

Hooks destructured as local aliases (e.g. Se=useRef, ne=useState):

_=Se(!0),[C,y]=ne(!0)  // true = ON by default

Patched:

_=Se(!0),[C,y]=ne(!1)  // false = OFF by default

Again the leading = anchors to the useRef-alias assignment, making the match unique.

The script auto-detects which format your bundle uses and applies the correct pattern. In both cases, the toggle button remains fully functional — only the default changes.

<#
.SYNOPSIS
Disables the auto-attach of open files / selections in Claude Code's IDE extension.
.DESCRIPTION
Patches the Claude Code webview bundle to default the file-attachment chip to OFF
(ide_opened_file / ide_selection no longer injected automatically). The toggle
button remains fully functional — click it ON when you want to attach the current file.
Supports VS Code, VSCodium, and Cursor extensions.
Uses webcrack to unpack the bundle for inspection, then patches the minified bundle.
Use -Hardcore to also excise the injection logic entirely (chip toggle does nothing).
.PARAMETER Hardcore
If set, removes the ide_opened_file/ide_selection injection block entirely
so the chip toggle has no effect — zero chance of accidental injection.
.PARAMETER Path
Custom path to the webview bundle to patch. Accepts either the index.js file
directly, or a directory containing webview\index.js. When omitted, the script
auto-detects the bundle across the standard extension directories.
.PARAMETER DryRun
If set, performs all detection, patching, and validation in memory but writes
NOTHING to disk (no backup, no file change). Prints the exact before/after so
you can review the change before applying it.
.LINK
https://github.com/anthropics/claude-code/issues/24726
https://github.com/anthropics/claude-code/issues/24726#issuecomment-4343376892
https://github.com/anthropics/claude-code/issues/24726#issuecomment-4577281297
.EXAMPLE
.\fix-auto-attach.ps1
Default behaviour: chip starts OFF but can be toggled ON.
.EXAMPLE
.\fix-auto-attach.ps1 -Hardcore
Aggressive: chip toggle does nothing, zero injection possible.
.EXAMPLE
.\fix-auto-attach.ps1 -Path "C:\path\to\index.js" -DryRun
Preview the patch against a custom bundle without writing anything.
#>
param(
[switch]$Hardcore,
[string]$Path,
[switch]$DryRun
)
$ErrorActionPreference = "Stop"
function Truncate-Text {
param(
[string]$Text,
[int]$Length = 300
)
if ($Text.Length -le $Length) { return $Text }
return $Text.Substring(0, $Length) + " ... [truncated]"
}
# --- 1. Locate the webview bundle ---
$bundlePath = $null
if ($Path) {
# Custom path supplied by the user
if (-not (Test-Path $Path)) {
Write-Host "ERROR: Custom path not found: $Path" -ForegroundColor Red
Write-Host ""
exit 1
}
$item = Get-Item $Path
if ($item.PSIsContainer) {
# Directory: prefer webview\index.js (extension root), fall back to
# index.js directly inside (e.g. the webview folder itself)
$candidate = Join-Path $item.FullName "webview\index.js"
if (-not (Test-Path $candidate)) {
$candidate = Join-Path $item.FullName "index.js"
}
if (Test-Path $candidate) {
$bundlePath = (Get-Item $candidate).FullName
} else {
Write-Host "ERROR: No webview\index.js or index.js found in directory: $Path" -ForegroundColor Red
Write-Host ""
exit 1
}
} else {
$bundlePath = $item.FullName
}
} else {
# Auto-detect across the standard extension directories
$searchPaths = @(
"$env:USERPROFILE\.vscode\extensions",
"$env:USERPROFILE\.vscode-server\extensions",
"$env:USERPROFILE\.vscode-oss\extensions",
"$env:USERPROFILE\.cursor\extensions",
"$env:USERPROFILE\.cursor-server\extensions"
)
$bundles = @()
foreach ($base in $searchPaths) {
$found = Get-ChildItem "$base\anthropic.claude-code-*\webview\index.js" -ErrorAction SilentlyContinue
$bundles += $found
}
Write-Host ""
if ($bundles.Count -eq 0) {
Write-Host "ERROR: No Claude Code extension webview found." -ForegroundColor Red
Write-Host ""
Write-Host "Checked paths:" -ForegroundColor Red
foreach ($p in $searchPaths) {
Write-Host " - ${p}\anthropic.claude-code-*\webview\index.js"
}
Write-Host ""
Write-Host "Tip: pass -Path to point at a specific bundle." -ForegroundColor Yellow
Write-Host ""
exit 1
}
if ($bundles.Count -gt 1) {
Write-Host "WARNING: Multiple Claude Code extensions found!" -ForegroundColor Yellow
foreach ($b in $bundles) {
Write-Host " $($b.FullName)"
}
Write-Host ""
Write-Host "Using the most recent: $($bundles[-1].FullName)" -ForegroundColor Cyan
Write-Host ""
}
$bundlePath = $bundles[-1].FullName
}
Write-Host ""
Write-Host "Found: $bundlePath" -ForegroundColor Green
# Extract version from extension path for display
if ($bundlePath -match 'anthropic\.claude-code-([^\\]+)') {
Write-Host "Extension version: $($matches[1])" -ForegroundColor Cyan
}
Write-Host ""
# --- 2. Create a backup ---
$backupPath = "${bundlePath}.bak"
if ($DryRun) {
Write-Host "DRY RUN: skipping backup creation." -ForegroundColor Yellow
} elseif (-not (Test-Path $backupPath)) {
Copy-Item $bundlePath $backupPath
Write-Host "Backup created: $backupPath" -ForegroundColor Cyan
} else {
Write-Host "Backup already exists: $backupPath (skipping)" -ForegroundColor Yellow
}
Write-Host ""
# --- 3. Read the bundle ---
$content = Get-Content $bundlePath -Raw
$oldContent = $content
# --- 4. Apply patch ---
$modeLabel = if ($Hardcore) { "HARDCORE" } else { "STANDARD" }
$patchType = $null
if ($Hardcore) {
# ----------------------------------------------------------------
# Hardcore mode: remove the if(J){...ide_opened_file...} block
# from the injection function entirely.
# The chip stays visible but its toggle does nothing.
#
# Works for all bundle formats (2.1.177, 2.1.211, etc.)
# ----------------------------------------------------------------
$pattern = '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>`\}\);'
$matchH = [regex]::Match($content, $pattern)
$beforeSnippet = $matchH.Value
$afterSnippet = ""
$content = $content -replace $pattern, ''
} else {
# ----------------------------------------------------------------
# Standard mode: flip useState(!0) -> useState(!1) so the chip
# defaults to OFF but the user can still toggle it ON per chat.
#
# Two bundle formats are supported:
#
# Format A (<=2.1.177): =Ke.useRef(!0),[v,x]=Ke.useState(!0)
# React hooks called via namespace (Ke.useRef / Ke.useState).
# Anchored on the leading = + distinctive useRef(!0) before useState(!0).
#
# Format B (>=2.1.211): =Se(!0),[C,y]=ne(!0)
# React hooks imported as direct aliases (Se=useRef, ne=useState).
# The leading = anchors to the useRef-alias assignment, making the
# generic `FUNC(!0),[X,Y]=FUNC(!0)` match unique and robust.
# ----------------------------------------------------------------
# Pattern A — legacy namespace hooks (2.1.177 and similar)
# Matches: =Ke.useRef(!0),[v,x]=Ke.useState(!0)
# Anchored on leading = to avoid false positives.
$patternA = '=(\w+)\.useRef\(!0\),\[(\w+),(\w+)\]=(\w+)\.useState\(!0\)'
$matchA = [regex]::Match($content, $patternA)
if ($matchA.Success) {
Write-Host "Detected bundle format: legacy namespace hooks (2.1.177 style)." -ForegroundColor Cyan
$content = $content -replace $patternA, '=$1.useRef(!0),[$2,$3]=$4.useState(!1)'
$patchType = "legacy"
$beforeSnippet = $matchA.Value
$afterSnippet = $matchA.Value -replace $patternA, '=$1.useRef(!0),[$2,$3]=$4.useState(!1)'
} else {
# Pattern B — direct hook imports (2.1.211+)
# Matches: =Se(!0),[C,y]=ne(!0)
# The leading = anchors this to the assignment of the useRef alias.
$patternB = '=(\w+)\(!0\),\[(\w+),(\w+)\]=(\w+)\(!0\)'
$matchB = [regex]::Match($content, $patternB)
if ($matchB.Success) {
Write-Host "Detected bundle format: direct hook imports (2.1.211+ style)." -ForegroundColor Cyan
$content = $content -replace $patternB, '=$1(!0),[$2,$3]=$4(!1)'
$patchType = "modern"
$beforeSnippet = $matchB.Value
$afterSnippet = $matchB.Value -replace $patternB, '=$1(!0),[$2,$3]=$4(!1)'
} else {
Write-Host "ERROR: No recognized chip-toggle pattern found in the bundle ($modeLabel mode)." -ForegroundColor Red
Write-Host ""
Write-Host "The extension version may have changed. Check the original issues for updated anchors:" -ForegroundColor Yellow
Write-Host " https://github.com/anthropics/claude-code/issues/24726#issuecomment-4343376892" -ForegroundColor Yellow
Write-Host " https://github.com/anthropics/claude-code/issues/24726#issuecomment-4577281297" -ForegroundColor Yellow
Write-Host ""
exit 1
}
}
}
if ($content -ceq $oldContent) {
Write-Host "ERROR: Patch pattern matched but replacement produced no change ($modeLabel mode)." -ForegroundColor Red
Write-Host ""
exit 1
}
if ($DryRun) {
Write-Host "DRY RUN: no changes written to disk." -ForegroundColor Yellow
Write-Host ""
Write-Host " BEFORE: $(Truncate-Text $beforeSnippet)" -ForegroundColor Red
Write-Host " AFTER: $(Truncate-Text $afterSnippet)" -ForegroundColor Green
Write-Host ""
Write-Host "Re-run WITHOUT -DryRun to apply this patch." -ForegroundColor Yellow
Write-Host ""
} else {
Set-Content $bundlePath -Value $content -NoNewline
Write-Host "Patch applied successfully! ($modeLabel mode)" -ForegroundColor Green
Write-Host ""
}
# --- 5. Validate ---
if ($Hardcore) {
# Check if any <ide_selection> injection blocks remain (the producer, not the parser)
$stillPresent = $content -match 'if\(\w+\)if\(\w+\.selectedText\)\w+\.push\(\{type:"text",text:`<ide_selection>'
if ($stillPresent) {
Write-Host "WARNING: ide_selection injection block still present in bundle -- patch may be incomplete." -ForegroundColor Yellow
} else {
Write-Host "Validation: ide_selection injection block removed from bundle." -ForegroundColor Green
}
} else {
if ($patchType -eq "legacy") {
# Check the flipped pattern — the =useRef(!0), prefix makes it unique
$matchCount = [regex]::Matches($content, '=\w+\.useRef\(!0\),\[\w+,\w+\]=\w+\.useState\(!1\)').Count
if ($matchCount -eq 1) {
Write-Host "Validation: 1 patched anchor found (legacy format, expected)." -ForegroundColor Green
} else {
Write-Host "WARNING: Expected 1 patched anchor (legacy), found $matchCount." -ForegroundColor Yellow
}
} else {
# Check the ORIGINAL pattern is gone — the flipped pattern has false
# positives against other `(!1)` states in the same component.
$origCount = [regex]::Matches($content, '=\w+\(!0\),\[\w+,\w+\]=\w+\(!0\)').Count
if ($origCount -eq 0) {
Write-Host "Validation: original pattern removed (modern format, expected)." -ForegroundColor Green
} else {
Write-Host "WARNING: Original pattern still has $origCount matches (modern)." -ForegroundColor Yellow
}
}
}
# --- 6. Instructions ---
$reloadKey = if ($env:OS -match 'Windows_NT') { "Ctrl+Shift+P" } else { "Cmd+Shift+P" }
Write-Host ""
if ($DryRun) {
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " DRY RUN - Nothing was written to disk." -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Re-run WITHOUT -DryRun to apply the patch." -ForegroundColor White
Write-Host ""
} else {
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " ${modeLabel} MODE - Fix applied!" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " 1. Press $reloadKey in VS Code / VSCodium / Cursor" -ForegroundColor White
Write-Host " 2. Run: `"Developer: Reload Window`"" -ForegroundColor White
Write-Host " 3. The auto-attach chip will now start OFF in new chats." -ForegroundColor White
Write-Host ""
Write-Host "To revert, restore the backup:" -ForegroundColor Yellow
Write-Host " Copy-Item -Path '${backupPath}' -Destination '${bundlePath}' -Force" -ForegroundColor Yellow
Write-Host ""
Write-Host "Then reload the window." -ForegroundColor Yellow
Write-Host ""
}
@sekedus

sekedus commented Jun 14, 2026

Copy link
Copy Markdown
Author

Tested on: Claude Code for VS Code 2.1.233

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment