Skip to content

Commit afe7f56

Browse files
netsnekclaude
andcommitted
Fix x86 native modules — replace with ARM64 from VS Code
The node_modules copied from Cursor's x86 AppImage contain x86-64 native .node files (sqlite3, spdlog, node-pty, parcel/watcher, etc.) which crash on ARM64. After grafting Cursor's JS, we now overwrite all .node files with their ARM64 equivalents from VS Code. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f221615 commit afe7f56

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

build-cursor-arm64.sh

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#!/bin/bash
22
# Build Cursor ARM64 by grafting Cursor's JS resources onto VS Code ARM64.
33
# Cursor is a closed-source VS Code fork — all proprietary code is JS (arch-independent).
4-
# Native binaries (Electron, Node) come from the open-source VS Code ARM64 build.
4+
# Native binaries (Electron, Node, .node modules) come from the open-source VS Code ARM64.
55
#
6-
# Cursor 2.x changed its AppImage structure:
7-
# Old (0.x): squashfs-root/resources/app/...
8-
# New (2.x): squashfs-root/usr/share/cursor/resources/app/...
9-
# This script handles both layouts.
6+
# IMPORTANT: Cursor's node_modules contain x86 native .node files. After copying,
7+
# we overwrite them with VS Code ARM64's native modules (same ABI, same versions).
108
set -euo pipefail
119

1210
WORKDIR="${WORKDIR:-/tmp/cursor-build}"
@@ -27,6 +25,8 @@ OFFSET=$(grep -aobP 'hsqs' cursor-x86.AppImage | tail -1 | cut -d: -f1)
2725
unsquashfs -o "$OFFSET" -d squashfs-root cursor-x86.AppImage
2826

2927
# 3. Detect app root (handles both old and new AppImage layouts)
28+
# Old (0.x): squashfs-root/resources/app/...
29+
# New (2.x): squashfs-root/usr/share/cursor/resources/app/...
3030
if [ -f "squashfs-root/usr/share/cursor/resources/app/product.json" ]; then
3131
APP_ROOT="squashfs-root/usr/share/cursor"
3232
elif [ -f "squashfs-root/resources/app/product.json" ]; then
@@ -47,9 +47,11 @@ echo "$CURSOR_VERSION" > "$OUTDIR/version.txt"
4747
echo "==> Downloading VS Code ARM64 $VSCODE_VERSION..."
4848
curl -Lo vscode-arm64.tar.gz \
4949
"https://update.code.visualstudio.com/${VSCODE_VERSION}/linux-arm64/stable"
50-
rm -rf vscode-arm64
51-
mkdir vscode-arm64
52-
tar xzf vscode-arm64.tar.gz -C vscode-arm64 --strip-components=1
50+
rm -rf vscode-arm64 vscode-arm64-clean
51+
mkdir vscode-arm64-clean
52+
tar xzf vscode-arm64.tar.gz -C vscode-arm64-clean --strip-components=1
53+
# Keep a clean copy for native module extraction
54+
cp -a vscode-arm64-clean vscode-arm64
5355

5456
# 6. Graft Cursor's proprietary JS onto VS Code ARM64
5557
echo "==> Grafting Cursor onto VS Code ARM64..."
@@ -67,26 +69,67 @@ for ext in "$APP_ROOT/resources/app/extensions/cursor-"* "$APP_ROOT/resources/ap
6769
[ -e "$ext" ] && cp -R "$ext" vscode-arm64/resources/app/extensions/
6870
done
6971

70-
# Node modules (both dir and asar may exist in 2.x)
71-
rm -rf vscode-arm64/resources/app/node_modules vscode-arm64/resources/app/node_modules.asar
72-
[ -d "$APP_ROOT/resources/app/node_modules" ] && \
73-
cp -R "$APP_ROOT/resources/app/node_modules" vscode-arm64/resources/app/
74-
[ -f "$APP_ROOT/resources/app/node_modules.asar" ] && \
75-
cp "$APP_ROOT/resources/app/node_modules.asar" vscode-arm64/resources/app/
76-
7772
# App resources (icons, etc.)
7873
rm -rf vscode-arm64/resources/app/resources
7974
cp -R "$APP_ROOT/resources/app/resources" vscode-arm64/resources/app/
8075

81-
# 7. Rename binary: code → cursor
76+
# 7. Handle node_modules: copy Cursor's JS, then fix native modules
77+
echo "==> Copying Cursor node_modules (JS code)..."
78+
rm -rf vscode-arm64/resources/app/node_modules
79+
cp -R "$APP_ROOT/resources/app/node_modules" vscode-arm64/resources/app/
80+
81+
# Copy node_modules.asar if present
82+
[ -f "$APP_ROOT/resources/app/node_modules.asar" ] && \
83+
cp "$APP_ROOT/resources/app/node_modules.asar" vscode-arm64/resources/app/
84+
85+
# Restore node_modules.asar.unpacked from VS Code ARM64
86+
rm -rf vscode-arm64/resources/app/node_modules.asar.unpacked
87+
[ -d "vscode-arm64-clean/resources/app/node_modules.asar.unpacked" ] && \
88+
cp -R "vscode-arm64-clean/resources/app/node_modules.asar.unpacked" vscode-arm64/resources/app/
89+
90+
# 8. Replace x86 native .node modules with ARM64 from VS Code
91+
echo "==> Replacing x86 native modules with ARM64..."
92+
find vscode-arm64-clean/resources/app/node_modules -name "*.node" -type f | while read arm64_file; do
93+
relpath="${arm64_file#vscode-arm64-clean/resources/app/node_modules/}"
94+
target="vscode-arm64/resources/app/node_modules/$relpath"
95+
if [ -f "$target" ]; then
96+
cp "$arm64_file" "$target"
97+
echo " replaced: $relpath"
98+
fi
99+
done
100+
101+
# Handle Cursor-only native modules:
102+
# @anysphere/policy-watcher → same as @vscode/policy-watcher
103+
VSCODE_PW="vscode-arm64-clean/resources/app/node_modules/@vscode/policy-watcher/build/Release/vscode-policy-watcher.node"
104+
CURSOR_PW="vscode-arm64/resources/app/node_modules/@anysphere/policy-watcher/build/Release/vscode-policy-watcher.node"
105+
if [ -f "$VSCODE_PW" ] && [ -f "$CURSOR_PW" ]; then
106+
cp "$VSCODE_PW" "$CURSOR_PW"
107+
echo " replaced: @anysphere/policy-watcher (from @vscode/policy-watcher)"
108+
fi
109+
110+
# cursor-proclist — x86-only, non-critical, remove
111+
PROCLIST="vscode-arm64/resources/app/node_modules/cursor-proclist/build/Release/cursor_proclist.node"
112+
[ -f "$PROCLIST" ] && rm "$PROCLIST" && echo " removed: cursor-proclist (x86-only, non-critical)"
113+
114+
# 9. Verify no x86 .node files remain in node_modules
115+
echo "==> Verifying architecture..."
116+
X86_COUNT=$(find vscode-arm64/resources/app/node_modules -name "*.node" -type f -exec file {} \; | grep -c "x86-64" || true)
117+
if [ "$X86_COUNT" -gt 0 ]; then
118+
echo "WARNING: $X86_COUNT x86-64 native modules still present:"
119+
find vscode-arm64/resources/app/node_modules -name "*.node" -type f -exec file {} \; | grep "x86-64"
120+
else
121+
echo " All clean — ARM64 only!"
122+
fi
123+
124+
# 10. Rename binary: code → cursor
82125
echo "==> Renaming binary..."
83126
mv vscode-arm64/code vscode-arm64/cursor 2>/dev/null || true
84127
mv vscode-arm64/bin/code vscode-arm64/bin/cursor 2>/dev/null || true
85128
sed -i 's|ELECTRON="$VSCODE_PATH/code"|ELECTRON="$VSCODE_PATH/cursor"|' vscode-arm64/bin/cursor
86129

87-
# 8. Extract icon
130+
# 11. Extract icon
88131
ICON=""
89-
for candidate in "$APP_ROOT/../co.anysphere.cursor.png" "squashfs-root/co.anysphere.cursor.png" "squashfs-root/cursor.png"; do
132+
for candidate in "squashfs-root/co.anysphere.cursor.png" "squashfs-root/cursor.png"; do
90133
[ -f "$candidate" ] && ICON="$candidate" && break
91134
done
92135
[ -n "$ICON" ] && cp "$ICON" "$OUTDIR/cursor.png"

0 commit comments

Comments
 (0)