Skip to content

Instantly share code, notes, and snippets.

@Tiryoh
Last active April 2, 2025 10:09
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-04-02-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="$(curl -s "$DOWNLOAD_LIST_URL" | grep -oE "https://downloads\.cursor\.com/production/[0-9a-fA-F]*/linux/x64(/appimage)?/${APPIMAGE_PREFIX}.*${APPIMAGE_SUFFIX}" | head -n 1)"
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"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment