Skip to content

Instantly share code, notes, and snippets.

@devotox
Forked from ColeMurray/patch-claude-code-extension.sh
Last active November 13, 2025 23:58
Show Gist options
  • Select an option

  • Save devotox/85e3624ba83406164c23a9be6c2023e1 to your computer and use it in GitHub Desktop.

Select an option

Save devotox/85e3624ba83406164c23a9be6c2023e1 to your computer and use it in GitHub Desktop.
claude code cursor extension yolo patch
#!/bin/bash
# Patch Claude Code Extension for Bypass Permissions
# Compatible with versions 2.0.1, 2.0.10, 2.0.15, 2.0.19, 2.0.22, 2.0.25, 2.0.28-2.0.37+
# Supports both VSCode and Cursor (all installations simultaneously)
VSCODE_EXTENSION_DIR="$HOME/.vscode/extensions"
CURSOR_EXTENSION_DIR="$HOME/.cursor/extensions"
EXTENSION_PATTERN="anthropic.claude-code-*"
# Use gsed if available (GNU sed), otherwise fall back to sed
if command -v gsed &> /dev/null; then
SED_CMD="gsed"
else
SED_CMD="sed"
fi
# Color codes for better output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
find_all_extensions() {
local extensions=()
# Check VSCode - find ALL matching extensions
if [ -d "$VSCODE_EXTENSION_DIR" ]; then
while IFS= read -r vscode_ext; do
[ -n "$vscode_ext" ] && extensions+=("$vscode_ext|VSCode")
done < <(find "$VSCODE_EXTENSION_DIR" -maxdepth 1 -type d -name "$EXTENSION_PATTERN" 2>/dev/null)
fi
# Check Cursor - find ALL matching extensions
if [ -d "$CURSOR_EXTENSION_DIR" ]; then
while IFS= read -r cursor_ext; do
[ -n "$cursor_ext" ] && extensions+=("$cursor_ext|Cursor")
done < <(find "$CURSOR_EXTENSION_DIR" -maxdepth 1 -type d -name "$EXTENSION_PATTERN" 2>/dev/null)
fi
printf '%s\n' "${extensions[@]}"
}
check_if_patched() {
local webview_js="$1"
if [ ! -f "$webview_js" ]; then
echo "not_found"
return
fi
# Check for bypassPermissions in mode array
if grep -q '\["bypassPermissions","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
echo "patched"
else
echo "unpatched"
fi
}
get_version_info() {
local ext_path="$1"
local version=$(basename "$ext_path" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+')
local arch=$(basename "$ext_path" | grep -o '\(darwin-arm64\|darwin-x64\|universal\)' || echo "")
if [ -n "$arch" ]; then
echo "$version ($arch)"
else
echo "$version"
fi
}
check_all_extensions() {
local extensions_info=($(find_all_extensions))
if [ ${#extensions_info[@]} -eq 0 ]; then
echo -e "${RED}❌ Claude Code extension not found in VSCode or Cursor${NC}"
echo "💡 Searched in:"
echo " - $VSCODE_EXTENSION_DIR"
echo " - $CURSOR_EXTENSION_DIR"
return 1
fi
echo -e "${BLUE}🔍 Found ${#extensions_info[@]} Claude Code installation(s)${NC}"
echo ""
for ext_info in "${extensions_info[@]}"; do
local ext_path="${ext_info%|*}"
local editor_name="${ext_info#*|}"
local version_info=$(get_version_info "$ext_path")
local webview_js="$ext_path/webview/index.js"
local patch_status=$(check_if_patched "$webview_js")
echo -e "📦 ${BLUE}$editor_name${NC} - v$version_info"
echo " Path: $ext_path"
if [ "$patch_status" = "patched" ]; then
echo -e " Status: ${GREEN}✅ Already patched${NC}"
elif [ "$patch_status" = "unpatched" ]; then
echo -e " Status: ${YELLOW}⚠️ Not patched${NC}"
else
echo -e " Status: ${RED}❌ Extension files not found${NC}"
fi
echo ""
done
return 0
}
patch_single_extension() {
local ext_path="$1"
local editor_name="$2"
local force="${3:-false}"
local version_info=$(get_version_info "$ext_path")
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "📦 ${BLUE}$editor_name${NC} - v$version_info"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local extension_js="$ext_path/extension.js"
local webview_js="$ext_path/webview/index.js"
# Check if already patched (before restoring)
if [ "$force" != "true" ]; then
local patch_status=$(check_if_patched "$webview_js")
if [ "$patch_status" = "patched" ]; then
# Double-check it's actually patched (not just from backup)
if ! [ -f "$webview_js.original" ]; then
echo -e "${GREEN}✅ Extension already patched (no backup found, assuming manual patch)${NC}"
return 0
fi
# If backup exists, check the backup is unpatched
local backup_status=$(check_if_patched "$webview_js.original")
if [ "$backup_status" = "unpatched" ]; then
echo -e "${GREEN}✅ Extension already patched (verified)${NC}"
return 0
fi
fi
fi
# If originals exist, restore them first to ensure clean patching
if [ -f "$extension_js.original" ]; then
echo "🔄 Restoring extension.js from backup before patching"
cp "$extension_js.original" "$extension_js"
else
echo "💾 Creating backup of extension.js"
cp "$extension_js" "$extension_js.original"
fi
if [ -f "$webview_js.original" ]; then
echo "🔄 Restoring webview/index.js from backup before patching"
cp "$webview_js.original" "$webview_js"
else
echo "💾 Creating backup of webview/index.js"
cp "$webview_js" "$webview_js.original"
fi
echo "🔧 Applying patches..."
# Patch 1: extension.js - Remove hardcoded "default" permission mode
# Pattern for v2.0.1: permissionMode:o===void 0?"default":o
# Pattern for v2.0.10: permissionMode:L="default"
# Pattern for v2.0.15+: permissionMode:N="default" (same for v2.0.19)
# Pattern for v2.0.36-v2.0.37: permissionMode:I="default"
# Note: v2.0.19 has BOTH v2.0.1 and v2.0.15+ patterns, patch all occurrences
local patched=false
if grep -q 'permissionMode:o===void 0?"default":o' "$extension_js" 2>/dev/null; then
# v2.0.1 pattern
$SED_CMD -i.bak 's/permissionMode:o===void 0?"default":o/permissionMode:o/g' "$extension_js"
echo " ✓ Patched extension.js (v2.0.1 pattern)"
patched=true
fi
if grep -q 'permissionMode:I="default"' "$extension_js" 2>/dev/null; then
# v2.0.36-v2.0.37 pattern
$SED_CMD -i.bak2 's/permissionMode:I="default"/permissionMode:I/g' "$extension_js"
echo " ✓ Patched extension.js (v2.0.36-v2.0.37 pattern)"
patched=true
fi
if grep -q 'permissionMode:N="default"' "$extension_js" 2>/dev/null; then
# v2.0.15+ pattern (includes v2.0.19)
$SED_CMD -i.bak3 's/permissionMode:N="default"/permissionMode:N/g' "$extension_js"
echo " ✓ Patched extension.js (v2.0.15+ pattern)"
patched=true
fi
if grep -q 'permissionMode:L="default"' "$extension_js" 2>/dev/null; then
# v2.0.10 pattern
$SED_CMD -i.bak4 's/permissionMode:L="default"/permissionMode:L/g' "$extension_js"
echo " ✓ Patched extension.js (v2.0.10 pattern)"
patched=true
fi
if [ "$patched" = false ]; then
echo -e " ${YELLOW}⚠️ Could not find permissionMode pattern in extension.js (may not be needed for this version)${NC}"
fi
# Patch 2: webview/index.js - Change mode array
# v2.0.1: Nye=["default","acceptEdits","plan"]
# v2.0.10: Fye=["default","acceptEdits","plan"]
# v2.0.15: wye=["default","acceptEdits","plan"]
# v2.0.19/v2.0.22: Sye=["default","acceptEdits","plan"]
# v2.0.25: Lye=["default","acceptEdits","plan"]
# v2.0.28-v2.0.34+: allowDangerouslySkipPermissions ternary operator
# v2.0.26-v2.0.27: Generic pattern matcher (if needed)
# Try specific known patterns first
local mode_array_patched=false
if grep -q 'Nye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/Nye=\["default","acceptEdits","plan"\]/Nye=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.1)"
mode_array_patched=true
elif grep -q 'Lye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/Lye=\["default","acceptEdits","plan"\]/Lye=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.25)"
mode_array_patched=true
elif grep -q 'Sye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/Sye=\["default","acceptEdits","plan"\]/Sye=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.19/v2.0.22)"
mode_array_patched=true
elif grep -q 'wye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/wye=\["default","acceptEdits","plan"\]/wye=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.15)"
mode_array_patched=true
elif grep -q 'Fye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/Fye=\["default","acceptEdits","plan"\]/Fye=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.10)"
mode_array_patched=true
elif grep -q 'allowDangerouslySkipPermissions?\["default","acceptEdits","plan","bypassPermissions"\]:\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
# v2.0.28-v2.0.34+: Ternary operator pattern with allowDangerouslySkipPermissions
$SED_CMD -i.bak 's/allowDangerouslySkipPermissions?\["default","acceptEdits","plan","bypassPermissions"\]:\["default","acceptEdits","plan"\]/allowDangerouslySkipPermissions?["default","acceptEdits","plan","bypassPermissions"]:["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.28-v2.0.34+ ternary pattern)"
mode_array_patched=true
else
# Generic pattern for older v2.0.26-v2.0.27 (if any)
# Match any variable name followed by =["default","acceptEdits","plan"]
if grep -qE '[A-Za-z]+ye=\["default","acceptEdits","plan"\]' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak 's/\([A-Za-z]*ye\)=\["default","acceptEdits","plan"\]/\1=["bypassPermissions","acceptEdits","plan"]/g' "$webview_js"
echo " ✓ Patched webview/index.js mode array (v2.0.26-v2.0.27 generic pattern)"
mode_array_patched=true
fi
fi
if [ "$mode_array_patched" = false ]; then
echo -e " ${RED}⚠️ Could not find mode array pattern in webview/index.js${NC}"
return 1
fi
# Patch 3: webview/index.js - Initialize session permissionMode to bypassPermissions
# v2.0.1-v2.0.10: permissionMode=kn("default")
# v2.0.15: permissionMode=fn("default")
# v2.0.19: permissionMode=un("default")
# v2.0.22/v2.0.28: permissionMode=cn("default")
# v2.0.25: permissionMode=ln("default")
# v2.0.29-v2.0.35: Generic pattern matcher (e.g., rn for v2.0.34)
# v2.0.36: permissionMode=Vi("default")
# v2.0.37: permissionMode=zi("default")
local session_init_patched=false
if grep -q 'permissionMode=ln("default")' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=ln("default")/permissionMode=ln("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.25)"
session_init_patched=true
elif grep -q 'permissionMode=cn("default")' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=cn("default")/permissionMode=cn("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.22)"
session_init_patched=true
elif grep -q 'permissionMode=un("default")' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=un("default")/permissionMode=un("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.19)"
session_init_patched=true
elif grep -q 'permissionMode=fn("default")' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=fn("default")/permissionMode=fn("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.15)"
session_init_patched=true
elif grep -q 'permissionMode=kn("default")' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=kn("default")/permissionMode=kn("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.1-v2.0.10)"
session_init_patched=true
else
# Generic pattern for newer versions (v2.0.29-v2.0.37+)
# Match permissionMode=XY("default") where XY can be any 1-3 letters (case-sensitive)
# Examples: rn (v2.0.34), Vi (v2.0.36), zi (v2.0.37), etc.
if grep -qE 'permissionMode=[A-Za-z]{1,3}\("default"\)' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak3 's/permissionMode=\([A-Za-z]*\)("default")/permissionMode=\1("bypassPermissions")/g' "$webview_js"
echo " ✓ Patched webview/index.js session init (v2.0.29-v2.0.37+ generic pattern)"
session_init_patched=true
fi
fi
if [ "$session_init_patched" = false ]; then
echo -e " ${RED}⚠️ Could not find session permissionMode initialization${NC}"
return 1
fi
# Patch 4: webview/index.js - Update UI text
# v2.0.1-v2.0.10: Uses (0,zr.jsxs) with Ph.footerButton and Pye
# v2.0.15: Uses fs.default.createElement with Oh.footerButton and vye
# v2.0.19: Uses ps.default.createElement with Bh.footerButton
# v2.0.22: Uses Cr.default.createElement with Bd.footerButton and yye
# v2.0.25: Uses yr.default.createElement with nl.footerButton and Sye
# v2.0.28: Uses Bo.default.createElement with Ba.footerButton
# v2.0.29-v2.0.37+: Generic pattern matcher (e.g., so for v2.0.34, lo for v2.0.37)
local ui_text_patched=false
if grep -q 'case"default":default:return yr.default.createElement("button",{type:"button",className:nl.footerButton' "$webview_js" 2>/dev/null; then
# v2.0.25 pattern
$SED_CMD -i.bak2 's/case"default":/case"bypassPermissions":/g' "$webview_js"
$SED_CMD -i.bak4 's/"Ask before edits"/"Bypass permissions"/g' "$webview_js"
$SED_CMD -i.bak5 's/Claude will ask before each edit/Claude will skip all permission prompts/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.25)"
ui_text_patched=true
elif grep -q 'case"default":default:return Cr.default.createElement("button",{type:"button",className:Bd.footerButton' "$webview_js" 2>/dev/null; then
# v2.0.22 pattern
$SED_CMD -i.bak2 's/case"default":/case"bypassPermissions":/g' "$webview_js"
$SED_CMD -i.bak4 's/"Ask before edits"/"Bypass permissions"/g' "$webview_js"
$SED_CMD -i.bak5 's/Claude will ask before each edit/Claude will skip all permission prompts/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.22)"
ui_text_patched=true
elif grep -q 'case"default":default:return ps.default.createElement("button",{type:"button",className:Bh.footerButton' "$webview_js" 2>/dev/null; then
# v2.0.19 pattern
$SED_CMD -i.bak2 's/case"default":/case"bypassPermissions":/g' "$webview_js"
$SED_CMD -i.bak4 's/"Ask before edits"/"Bypass permissions"/g' "$webview_js"
$SED_CMD -i.bak5 's/Claude will ask before each edit/Claude will skip all permission prompts/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.19)"
ui_text_patched=true
elif grep -q 'case"default":default:return fs.default.createElement("button",{type:"button",className:Oh.footerButton' "$webview_js" 2>/dev/null; then
# v2.0.15 pattern
$SED_CMD -i.bak2 's/case"default":/case"bypassPermissions":/g' "$webview_js"
$SED_CMD -i.bak4 's/"Ask before edits"/"Bypass permissions"/g' "$webview_js"
$SED_CMD -i.bak5 's/Claude will ask before each edit/Claude will skip all permission prompts/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.15)"
ui_text_patched=true
elif grep -q 'case"default":default:return(0,zr.jsxs)("button",{type:"button",className:Ph.footerButton,onClick:e,title:"Claude will ask before each edit' "$webview_js" 2>/dev/null; then
# v2.0.1-v2.0.10 pattern
$SED_CMD -i.bak2 's/case"default":default:return(0,zr.jsxs)("button",{type:"button",className:Ph.footerButton,onClick:e,title:"Claude will ask before each edit\. Click, or press Shift+Tab, to switch modes\.",children:\[(0,zr.jsx)(Pye,{}),(0,zr.jsx)("span",{children:"Ask before edits"})\]})/case"bypassPermissions":default:return(0,zr.jsxs)("button",{type:"button",className:Ph.footerButton,onClick:e,title:"Claude will skip all permission prompts. Click, or press Shift+Tab, to switch modes.",children:[(0,zr.jsx)(Pye,{}),(0,zr.jsx)("span",{children:"Bypass permissions"})]})/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.1-v2.0.10)"
ui_text_patched=true
else
# Generic pattern for newer versions (v2.0.29-v2.0.37+)
# Look for createElement pattern and apply simple string replacements
# Examples: so.default.createElement (v2.0.34), Bo.default.createElement, lo.default.createElement (v2.0.37), etc.
if grep -qE 'case"default":default:return [A-Za-z]+\.default\.createElement\("button"' "$webview_js" 2>/dev/null; then
$SED_CMD -i.bak2 's/case"default":/case"bypassPermissions":/g' "$webview_js"
$SED_CMD -i.bak4 's/"Ask before edits"/"Bypass permissions"/g' "$webview_js"
$SED_CMD -i.bak5 's/Claude will ask before each edit/Claude will skip all permission prompts/g' "$webview_js"
echo " ✓ Patched webview/index.js UI text (v2.0.29-v2.0.37+ generic pattern)"
ui_text_patched=true
fi
fi
if [ "$ui_text_patched" = false ]; then
echo -e " ${RED}⚠️ Could not find UI text pattern in webview/index.js${NC}"
return 1
fi
# Clean up .bak files
rm -f "$extension_js.bak" "$extension_js.bak2" "$extension_js.bak3" "$webview_js.bak" "$webview_js.bak2" "$webview_js.bak3" "$webview_js.bak4" "$webview_js.bak5"
echo -e "${GREEN}✅ Patching complete for $editor_name!${NC}"
echo "🔄 Please reload $editor_name (Cmd+Shift+P → 'Developer: Reload Window')"
return 0
}
patch_all_extensions() {
local force="${1:-false}"
local extensions_info=($(find_all_extensions))
if [ ${#extensions_info[@]} -eq 0 ]; then
echo -e "${RED}❌ Claude Code extension not found in VSCode or Cursor${NC}"
echo "💡 Searched in:"
echo " - $VSCODE_EXTENSION_DIR"
echo " - $CURSOR_EXTENSION_DIR"
return 1
fi
echo -e "${BLUE}🔍 Found ${#extensions_info[@]} Claude Code installation(s)${NC}"
local success_count=0
local already_patched=0
local failed_count=0
for ext_info in "${extensions_info[@]}"; do
local ext_path="${ext_info%|*}"
local editor_name="${ext_info#*|}"
if patch_single_extension "$ext_path" "$editor_name" "$force"; then
# Check if it was already patched or newly patched
if grep -q "already patched" <<< "$(patch_single_extension "$ext_path" "$editor_name" "$force" 2>&1)"; then
((already_patched++))
fi
((success_count++))
else
((failed_count++))
fi
done
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
if [ $failed_count -eq 0 ]; then
echo -e "${GREEN}✅ Successfully processed $success_count of ${#extensions_info[@]} installation(s)${NC}"
else
echo -e "${YELLOW}⚠️ Processed: $success_count successful, $failed_count failed${NC}"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
return 0
}
restore_all_originals() {
local extensions_info=($(find_all_extensions))
if [ ${#extensions_info[@]} -eq 0 ]; then
echo -e "${RED}❌ Claude Code extension not found in VSCode or Cursor${NC}"
return 1
fi
echo "🔄 Restoring original files..."
for ext_info in "${extensions_info[@]}"; do
local ext_path="${ext_info%|*}"
local editor_name="${ext_info#*|}"
local version_info=$(get_version_info "$ext_path")
echo ""
echo -e "📦 ${BLUE}$editor_name${NC} - v$version_info"
local restored=false
if [ -f "$ext_path/extension.js.original" ]; then
cp "$ext_path/extension.js.original" "$ext_path/extension.js"
echo " ✅ Restored extension.js"
restored=true
fi
if [ -f "$ext_path/webview/index.js.original" ]; then
cp "$ext_path/webview/index.js.original" "$ext_path/webview/index.js"
echo " ✅ Restored webview/index.js"
restored=true
fi
if [ "$restored" = false ]; then
echo " ℹ️ No backup files found (extension not patched or manually installed)"
fi
done
echo ""
echo -e "${GREEN}✅ Restoration complete!${NC}"
}
show_help() {
cat << EOF
Usage: $0 [OPTIONS]
Patch Claude Code Extension for Bypass Permissions
Automatically detects and patches all VSCode and Cursor installations
OPTIONS:
(none) Patch all found installations (skips already patched)
--check Check status of all installations without patching
--force Force re-patch even if already patched
--restore Restore original files from backups
--help Show this help message
SUPPORTED VERSIONS:
2.0.1, 2.0.10, 2.0.15, 2.0.19, 2.0.22, 2.0.25, 2.0.28-2.0.37+
(Generic patterns support future versions automatically)
SUPPORTED EDITORS:
- VSCode ($VSCODE_EXTENSION_DIR)
- Cursor ($CURSOR_EXTENSION_DIR)
EXAMPLES:
$0 # Patch all unpatched installations
$0 --check # Check status without patching
$0 --force # Re-patch all installations
$0 --restore # Restore original files
EOF
}
# Parse command line arguments
case "${1:-}" in
--check)
check_all_extensions
;;
--force)
patch_all_extensions "true"
;;
--restore)
restore_all_originals
;;
--help|-h)
show_help
;;
"")
patch_all_extensions "false"
;;
*)
echo -e "${RED}❌ Unknown option: $1${NC}"
echo ""
show_help
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment