Skip to content

Instantly share code, notes, and snippets.

@levity
Created April 25, 2026 00:49
Show Gist options
  • Select an option

  • Save levity/9b39a7c35c6035a60608fb735e3ccc07 to your computer and use it in GitHub Desktop.

Select an option

Save levity/9b39a7c35c6035a60608fb735e3ccc07 to your computer and use it in GitHub Desktop.
patch Figma.app to allow remote debugging
#!/bin/bash
# figma-debug-start
# Stand-alone launcher: patches Figma (if needed) and starts with remote debugging.
# - No dependency on this repo's JS files
# - No dependency on project working directory
# - No automatic package installation (safer for supply-chain)
# - If CDP is already reachable, it does NOT restart Figma
set -euo pipefail
PORT="${FIGMA_DEBUG_PORT:-9222}"
NO_KILL=false
for arg in "$@"; do
case "$arg" in
--no-kill) NO_KILL=true ;;
-h|--help)
cat <<EOF
Usage: figma-debug-start [options]
Options:
--no-kill Do not kill running Figma before trying to start debug mode
-h, --help Show help
Environment:
FIGMA_DEBUG_PORT Override debug port (default: 9222)
EOF
exit 0
;;
esac
done
if [[ "$(uname -s)" != "Darwin" ]]; then
echo "This standalone script currently supports macOS only."
exit 1
fi
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BOLD='\033[1m'
NC='\033[0m'
FIGMA_APP="/Applications/Figma.app"
ASAR_PATH="$FIGMA_APP/Contents/Resources/app.asar"
require_cmd() {
local cmd="$1"
if ! command -v "$cmd" >/dev/null 2>&1; then
echo -e "${RED}Missing required command: '$cmd'. Please install it and retry.${NC}"
exit 1
fi
}
cdp_ready() {
local code
code=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:${PORT}/json" || true)
[[ "$code" == "200" ]]
}
is_figma_running() {
pgrep -x "Figma" >/dev/null 2>&1
}
require_cmd curl
require_cmd python3
require_cmd codesign
if [[ ! -d "$FIGMA_APP" ]]; then
echo -e "${RED}Figma not found at $FIGMA_APP${NC}"
exit 1
fi
# IMPORTANT: If already running with CDP, do not restart.
if cdp_ready; then
echo -e "${GREEN}✓ Figma already running with remote debugging on localhost:${PORT}${NC}"
exit 0
fi
if [[ ! -f "$ASAR_PATH" ]]; then
echo -e "${RED}Could not find app.asar at: $ASAR_PATH${NC}"
exit 1
fi
BLOCK='removeSwitch("remote-debugging-port")'
PATCH='removeSwitch("remote-debugXing-port")'
PATCH_STATUS=$(python3 - "$ASAR_PATH" <<'PY'
import sys
path = sys.argv[1]
b = open(path, 'rb').read()
block = b'removeSwitch("remote-debugging-port")'
patch = b'removeSwitch("remote-debugXing-port")'
cb = b.count(block)
cp = b.count(patch)
if cp >= 1 and cb == 0:
print('already_patched')
elif cb == 1 and cp == 0:
print('patchable')
elif cb == 0 and cp == 0:
print('unknown_format')
else:
print(f'suspicious:{cb}:{cp}')
PY
)
if [[ "$PATCH_STATUS" == "already_patched" ]]; then
echo -e "${GREEN}✓ Figma binary already patched${NC}"
elif [[ "$PATCH_STATUS" == "patchable" ]]; then
echo "Patching Figma binary (single known-string replacement)..."
BACKUP_DIR="$HOME/.figma-debug-start/backups"
mkdir -p "$BACKUP_DIR"
BACKUP_PATH="$BACKUP_DIR/app.asar.$(date +%Y%m%d-%H%M%S).bak"
cp "$ASAR_PATH" "$BACKUP_PATH"
python3 - "$ASAR_PATH" <<'PY'
import sys
path = sys.argv[1]
block = b'removeSwitch("remote-debugging-port")'
patch = b'removeSwitch("remote-debugXing-port")'
b = open(path, 'rb').read()
if b.count(block) != 1 or b.count(patch) != 0:
raise SystemExit('Refusing patch: unexpected pre-state')
b2 = b.replace(block, patch, 1)
if b2.count(block) != 0 or b2.count(patch) < 1:
raise SystemExit('Refusing patch: verification failed')
open(path, 'wb').write(b2)
PY
echo "Re-signing Figma app..."
if codesign --force --deep --sign - "$FIGMA_APP" >/dev/null 2>&1; then
echo -e "${GREEN}✓ Patch applied and app re-signed${NC}"
else
echo -e "${YELLOW}Patch applied, but re-signing failed (Figma may still run).${NC}"
fi
elif [[ "$PATCH_STATUS" == "unknown_format" ]]; then
echo -e "${YELLOW}Could not find expected patch target in app.asar.${NC}"
echo -e "${YELLOW}Figma version may have changed; continuing to launch anyway.${NC}"
else
echo -e "${RED}Suspicious/ambiguous patch state detected: $PATCH_STATUS${NC}"
echo -e "${RED}Refusing to modify app.asar automatically.${NC}"
exit 1
fi
if is_figma_running; then
if [[ "$NO_KILL" == "true" ]]; then
echo -e "${YELLOW}Figma is already running and --no-kill was set.${NC}"
echo "Attempting to launch with debug args without restart..."
open -a Figma --args "--remote-debugging-port=${PORT}" >/dev/null 2>&1 || true
else
echo "Restarting Figma to apply debug args..."
killall Figma >/dev/null 2>&1 || true
sleep 1
open -a Figma --args "--remote-debugging-port=${PORT}" >/dev/null 2>&1
fi
else
echo "Starting Figma with remote debugging..."
open -a Figma --args "--remote-debugging-port=${PORT}" >/dev/null 2>&1
fi
for _ in {1..30}; do
if cdp_ready; then
echo -e "${GREEN}✓ Figma ready with remote debugging on localhost:${PORT}${NC}"
exit 0
fi
sleep 1
done
echo -e "${RED}Figma started, but remote debugging is not reachable yet.${NC}"
if [[ "$NO_KILL" == "true" ]]; then
echo -e "${YELLOW}Try again without --no-kill so Figma can restart with debug args.${NC}"
fi
exit 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment