Skip to content

Instantly share code, notes, and snippets.

@Tiryoh
Last active June 5, 2025 03:31
Show Gist options
  • Save Tiryoh/2fac7de1a90e23fa21dcdac898dd2694 to your computer and use it in GitHub Desktop.
Save Tiryoh/2fac7de1a90e23fa21dcdac898dd2694 to your computer and use it in GitHub Desktop.
Cursor Installation Script for Ubuntu (supports 0.46 or later)
#!/bin/bash
set -euo pipefail
# script version: 2025-05-15-1
# reference: https://zenn.dev/ka2kama/articles/f0a6b5c2f32c87
# Step 0: Check dependencies
if [ -z "$(which curl)" ]; then
echo curl command not found!
exit 1
fi
if [ -z "$(which update-desktop-database)" ]; then
echo update-desktop-database command not found!
exit 1
fi
# Step 1: Declare installation paths and variables
CURSOR_DIR="$HOME/Applications/cursor"
APPIMAGE_DIR="$CURSOR_DIR/images"
EXTRACTED_DIR="$CURSOR_DIR/squashfs-root"
BIN_PATH="$EXTRACTED_DIR/usr/bin/cursor"
DESKTOP_DIR="$HOME/.local/share/applications"
DESKTOP_FILE_PATH="$DESKTOP_DIR/cursor.desktop"
SCRIPT_PATH="$HOME/.local/bin/cursor"
ICON_PATH="$HOME/.local/share/icons/cursor.png"
LOG_FILE_PATH="$HOME/.local/share/cursor/cursor.log"
# DOWNLOAD_URL="https://downloader.cursor.sh/linux/appImage/x64" # only availabe for version before 0.46.0
DOWNLOAD_URL=""
DOWNLOAD_LIST_URL="https://raw.githubusercontent.com/oslook/cursor-ai-downloads/refs/heads/main/README.md"
APPIMAGE_PREFIX_REV1="cursor-" # only availabe for version before 0.46.0
APPIMAGE_SUFFIX_REV1="x86_64.AppImage" # only availabe for version before 0.46.0
APPIMAGE_PREFIX_REV2="Cursor-" # only availabe for version 0.46 and 0.47
APPIMAGE_SUFFIX_REV2="-[0-9a-fA-F]{40}\.deb\.glibc.*-x86_64\.AppImage" # only availabe for version 0.46 and 0.47
APPIMAGE_PREFIX="Cursor-"
APPIMAGE_SUFFIX="-x86_64\.AppImage"
MAX_KEEP_INSTALLED_VERSIONS=3
# Step 2: Create required directories
mkdir -p "$APPIMAGE_DIR" \
"$DESKTOP_DIR" \
"$(dirname "$SCRIPT_PATH")" \
"$(dirname "$ICON_PATH")" \
"$(dirname "$LOG_FILE_PATH")"
cd "$CURSOR_DIR"
# Step 3: Download latest version if not already installed
# 3.1: Check current installation
CURRENT_APPIMAGE_PATH=$(find "$APPIMAGE_DIR" -name "$APPIMAGE_PREFIX*AppImage" -printf '%f\n' \
| sort -Vr \
| head -n 1)
if [ -z "${CURRENT_APPIMAGE_PATH}" ]; then
CURRENT_APPIMAGE_PATH=$(find "$APPIMAGE_DIR" -name "$APPIMAGE_PREFIX_REV1*AppImage" -printf '%f\n' \
| sort -Vr \
| head -n 1)
fi
CURRENT_VERSION=$(basename "$CURRENT_APPIMAGE_PATH" | sed -E "s/^$APPIMAGE_PREFIX//; s/$APPIMAGE_SUFFIX$//")
# 3.2: Fetch latest version information
#LATEST_APPIMAGE=$(curl --range 0-0 -si "$DOWNLOAD_URL" \
# | grep -i 'Content-Disposition' \
# | awk -F'filename=' '{print $2}' \
# | tr -d '\r\n"') # only availabe for version before 0.46.0
if [ -z "$DOWNLOAD_URL" ]; then
DOWNLOAD_URL="$(data=$(curl -s "$DOWNLOAD_LIST_URL") && grep -m1 -oE "https://downloads\.cursor\.com/production/[0-9a-fA-F]*/linux/x64(/appimage)?/${APPIMAGE_PREFIX}.*${APPIMAGE_SUFFIX}" <<< "$data")"
fi
LATEST_APPIMAGE=$(echo "$DOWNLOAD_URL" | sed -E "s#.*/(Cursor-[^/]+\.AppImage)#\1#")
LATEST_VERSION=$(echo "$LATEST_APPIMAGE" | sed -E "s/^$APPIMAGE_PREFIX//; s/$APPIMAGE_SUFFIX$//")
echo "Current: $CURRENT_VERSION"
echo "Latest : $LATEST_VERSION"
# 3.3: Download new version if not installed
if [ "$CURRENT_VERSION" != "$LATEST_VERSION" ]; then
echo "Downloading $LATEST_APPIMAGE..."
trap "rm -f ""$APPIMAGE_DIR"/"$LATEST_APPIMAGE""; echo -e '\nDownload cancelled. Cleaning up...'; exit 1" SIGINT
# curl -LOJ --remove-on-error "$DOWNLOAD_URL" --output-dir "$APPIMAGE_DIR" # this is availabe for Ubuntu 24.04 or later
# curl -LOJ "$DOWNLOAD_URL" --output-dir "$APPIMAGE_DIR" # this is availabe for Ubuntu 22.04 or later
pushd "$APPIMAGE_DIR" && curl -LOJ "$DOWNLOAD_URL" && popd
chmod +x "$APPIMAGE_DIR/$LATEST_APPIMAGE"
# Remove old AppImages, keeping only a constant number of versions
find "$APPIMAGE_DIR" -name "$APPIMAGE_PREFIX*$APPIMAGE_SUFFIX" \
| sort -Vr \
| tail -n +$((MAX_KEEP_INSTALLED_VERSIONS + 1)) \
| xargs rm -f
else
echo "Already downloaded the latest version ($LATEST_VERSION)"
fi
# Step 4: Extract application binary
rm -rf "$EXTRACTED_DIR"
"$APPIMAGE_DIR/$LATEST_APPIMAGE" --appimage-extract
chmod +x "$BIN_PATH"
# Step 5: Configure application launcher
cat <<EOF > "$SCRIPT_PATH"
#!/bin/bash
# Show version number when --version or -v flag is used
if [ "\$1" = "--version" ] || [ "\$1" = "-v" ]; then
echo "Cursor version: $LATEST_VERSION"
exit 0
fi
"$BIN_PATH" --no-sandbox "\$@" 2>&1 \
| grep -v '@todesktop/runtime: skipping autoUpdater initialization because application is not in AppImage.' \
>> "$LOG_FILE_PATH"
EOF
chmod +x "$SCRIPT_PATH"
# Step 6: Install application icon
cp "$EXTRACTED_DIR/code.png" "$ICON_PATH"
# Step 7: Create desktop integration
if [ ! -f "$DESKTOP_FILE_PATH" ] \
|| [ "$(grep -oP '(?<=^Exec=).*' "$DESKTOP_FILE_PATH")" != "$SCRIPT_PATH" ] \
|| [ "$(grep -oP '(?<=^Icon=).*' "$DESKTOP_FILE_PATH")" != "$ICON_PATH" ]; then
cat <<EOF > "$DESKTOP_FILE_PATH"
[Desktop Entry]
Name=Cursor
Exec=$SCRIPT_PATH
Terminal=false
Type=Application
Icon=$ICON_PATH
StartupWMClass=Cursor
Comment=AI-powered code editor
MimeType=x-scheme-handler/cursor;
Categories=Utility;Development
EOF
chmod +x "$DESKTOP_FILE_PATH"
echo "Desktop shortcut created successfully"
fi
# Step 8: Update system's desktop database
update-desktop-database "$DESKTOP_DIR"
@Tiryoh
Copy link
Author

Tiryoh commented Jun 5, 2025

Confirmed this works with v1.0.0

image

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