Skip to content

Instantly share code, notes, and snippets.

@scottdavis
Last active October 21, 2025 14:28
Show Gist options
  • Select an option

  • Save scottdavis/840c00bdea7e562416b9bf18d0cd7faf to your computer and use it in GitHub Desktop.

Select an option

Save scottdavis/840c00bdea7e562416b9bf18d0cd7faf to your computer and use it in GitHub Desktop.
cursor-update-arch
#!/bin/bash
# Default installation directory and app name
INSTALL_DIR="$HOME/opt"
APP_NAME="Cursor"
APP_URL="https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable"
USER_AGENT="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
# Parse command line arguments
FORCE_UPDATE=false
while [[ $# -gt 0 ]]; do
case $1 in
-f|--force)
FORCE_UPDATE=true
shift
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -f, --force Force update even if latest version is already installed"
echo " -h, --help Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
# Function to display error messages
error_exit() {
echo "Error: $1"
exit 1
}
# Function to download a file
download_file() {
local url="$1"
local output="$2"
curl -L -A "$USER_AGENT" -o "$output" "$url" || error_exit "Failed to download $output."
}
# Function to parse JSON and extract download URL
parse_api_response() {
local json_file="$1"
local download_url=$(jq -r '.downloadUrl' "$json_file" 2>/dev/null)
local version=$(jq -r '.version' "$json_file" 2>/dev/null)
if [[ "$download_url" == "null" || -z "$download_url" ]]; then
error_exit "Failed to parse download URL from API response"
fi
echo "$download_url|$version"
}
# Ensure required tools are installed
command -v curl &>/dev/null || error_exit "curl is required. Please install curl and try again."
command -v jq &>/dev/null || error_exit "jq is required for JSON parsing. Please install jq and try again."
# Create installation directory
mkdir -p "$INSTALL_DIR" || error_exit "Failed to create directory $INSTALL_DIR"
# Fetch existing file, if any
existing_file=$(ls "$INSTALL_DIR"/*.AppImage 2>/dev/null | head -n 1)
echo -e "\n> Fetching the latest version of Cursor...\n"
# Download API response
api_response="$INSTALL_DIR/cursor-api.json"
download_file "$APP_URL" "$api_response"
# Parse API response to get download URL and version
api_data=$(parse_api_response "$api_response")
download_url=$(echo "$api_data" | cut -d'|' -f1)
version=$(echo "$api_data" | cut -d'|' -f2)
echo "> Found version: $version"
echo "> Downloading from: $download_url"
# Download latest version of Cursor
latest_file="$INSTALL_DIR/cursor-latest.AppImage"
download_file "$download_url" "$latest_file"
# Clean up API response file
rm -f "$api_response"
# Check if the download was successful
if [[ -f "$latest_file" && -s "$latest_file" ]]; then
echo -e "\n> Download complete."
# Check if we already have this version (unless forcing update)
if [[ "$existing_file" && "$FORCE_UPDATE" == false ]]; then
# Try to extract version from existing file name or use file comparison as fallback
existing_version=$(basename "$existing_file" | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | head -n1)
if [[ "$existing_version" == "$version" ]]; then
echo -e "\n> Already up to date (version $version). No new version available."
echo -e "> Use -f or --force to update anyway."
rm "$latest_file"
exit 0
elif [[ -z "$existing_version" ]] && cmp -s "$existing_file" "$latest_file"; then
echo -e "\n> Already up to date. No new version available."
echo -e "> Use -f or --force to update anyway."
rm "$latest_file"
exit 0
fi
elif [[ "$FORCE_UPDATE" == true ]]; then
echo -e "\n> Force update enabled. Proceeding with update..."
fi
chmod +x "$latest_file"
[[ "$existing_file" ]] && rm "$existing_file"
mv "$latest_file" "$INSTALL_DIR/cursor.AppImage"
echo -e "\n> Cursor has been updated successfully to version $version."
echo -e "\n> Updating desktop entry..."
icon_path="$HOME/opt/cursor.png"
desktop_file="/usr/share/applications/$APP_NAME.desktop"
# Download the icon if it doesn't exist
[[ ! -f "$icon_path" ]] && {
sudo mkdir -p "$(dirname "$icon_path")"
download_file "https://cursor.com/assets/images/logo.png" "$icon_path"
}
# Create or update desktop entry
cat <<EOF | sudo tee "$desktop_file" >/dev/null
[Desktop Entry]
Name=Cursor
Exec=$INSTALL_DIR/cursor.AppImage
Terminal=false
Type=Application
Icon=$icon_path
StartupWMClass=Cursor
X-AppImage-Version=latest
Comment=Cursor is an AI-first coding environment.
MimeType=x-scheme-handler/cursor;
Categories=Utility;Development
EOF
sudo chmod +x "$desktop_file"
echo -e "\n> Desktop entry updated successfully. You can launch Cursor from your application menu."
echo -e "\n> Creating cursor command link..."
# Create cursor command in user's bin directory
user_bin_dir="$HOME/bin"
mkdir -p "$user_bin_dir"
cursor_cmd="$user_bin_dir/cursor"
# Create a wrapper script that launches the AppImage
cat <<EOF > "$cursor_cmd"
#!/bin/bash
exec "$INSTALL_DIR/cursor.AppImage" "\$@"
EOF
chmod +x "$cursor_cmd"
# Check if ~/bin is in PATH
if [[ ":$PATH:" != *":$user_bin_dir:"* ]]; then
echo -e "\n> Note: $user_bin_dir is not in your PATH."
echo -e "> Add the following line to your ~/.bashrc or ~/.profile to use the 'cursor' command:"
echo -e "> export PATH=\"\$HOME/bin:\$PATH\""
echo -e "> Then run: source ~/.bashrc (or restart your terminal)"
else
echo -e "\n> Cursor command created successfully. You can now use 'cursor' from the command line."
fi
else
error_exit "Failed to download Cursor. Please check yaour internet connection or try again."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment