[Tutorial] Install Cursor permanently when AppImage install didn't work on Linux

I found it necessary to remove appimagelauncher as well as installing libfuse in order to run Cursor.

fuse - Can’t run an AppImage on Ubuntu 20.04 - Ask Ubuntu

As none of these links within the script work anymore, can someone update this?

specifically the download.cursor.sh the sh isn’t correct.

1 Like

Just came here to ask the same. :face_with_head_bandage:

Updated update-cursor.sh:

#!/bin/bash

# Set the known AppImage version
APPIMAGE_VERSION="0.49.6"
FILENAME="Cursor-${APPIMAGE_VERSION}-x86_64.AppImage"
DOWNLOAD_URL="https://downloads.cursor.com/production/0781e811de386a0c5bcb07ceb259df8ff8246a52/linux/x64/${FILENAME}"

# Target filename
OUTPUT_FILE="cursor.AppImage"

# Download and rename
echo "Downloading Cursor AppImage version ${APPIMAGE_VERSION}..."
wget "$DOWNLOAD_URL" -O "$OUTPUT_FILE"

# Make it executable
chmod +x "$OUTPUT_FILE"

echo "Downloaded and saved as: $OUTPUT_FILE"

You might be interested in another installer and updater:

Thanks a lot for this tutorial.

I have created a script in Python that gets the latest version and checks if already installed.

Run this:

nano ~/Applications/cursor/update-cursor.py

Then paste the content (you can modify API_URL to suit your needs):

#!/usr/bin/env python3

import os
import requests
from packaging import version

APPDIR = os.path.expanduser("~/Applications/cursor")
VERSION_FILE = os.path.join(APPDIR, "version")
API_URL = "https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable"

def get_current_version():
    try:
        with open(VERSION_FILE, "r") as f:
            return f.read().strip()
    except FileNotFoundError:
        return None

def get_latest_release_info():
    response = requests.get(API_URL)
    response.raise_for_status()
    return response.json()

def download_appimage(download_url, target_path):
    print(f"Downloading new version to {target_path}...")
    with requests.get(download_url, stream=True) as r:
        r.raise_for_status()
        with open(target_path, "wb") as f:
            for chunk in r.iter_content(chunk_size=8192):
                f.write(chunk)
    os.chmod(target_path, 0o755)
    print("Download complete and permissions updated.")

def main():
    os.makedirs(APPDIR, exist_ok=True)

    current_version = get_current_version()
    print(f"Current version: {current_version or 'None'}")

    release_info = get_latest_release_info()
    latest_version = release_info["version"]
    download_url = release_info["downloadUrl"]

    if current_version is None or version.parse(latest_version) > version.parse(current_version):
        appimage_path = os.path.join(APPDIR, "cursor.AppImage")
        download_appimage(download_url, appimage_path)
        with open(VERSION_FILE, "w") as f:
            f.write(latest_version)
        print(f"Version {latest_version} installed successfully.")
    else:
        print("No update needed. You're already using the latest version.")

if __name__ == "__main__":
    main()

Make it executable:

chmod +x ~/Applications/cursor/update-cursor.py

Install dependencies (if not already installed):

pip install requests packaging

Change the filepath to update-cursor.py in ~/.config/systemd/user/update-cursor.service

nano ~/.config/systemd/user/update-cursor.service

The content should be:

[Unit]
Description=Update Cursor

[Service]
ExecStart=/home/your_username/Applications/cursor/update-cursor.py
Type=oneshot

[Install]
WantedBy=default.target

(change your_username by your actual username.)

Hi All,

This is my first time sharing a script like this, so please forgive any mistakes or areas for improvement. Your corrections and suggestions would be greatly appreciated. Thank you!

I have tested the below script in Ubuntu 22 and 24 LTS. It will download, install, and update, and if required, it will remove the Cursor app as per the user’s input. This will also add an application shortcut in application menu.

1. Create the script for the installer.

nano ~/cursor.sh

2. Copy the code into the file, “cursor.sh”, then save and exit the editor

#!/bin/bash

set -e

# Constants
APPIMAGE_NAME="Cursor.AppImage"
INSTALL_DIR="/opt"
EXTRACTED_DIR="$INSTALL_DIR/squashfs-root"
DESKTOP_ENTRY="/usr/share/applications/cursor.desktop"
SYMLINK="/usr/local/bin/cursor"
DOWNLOAD_API="https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable"

function download_cursor() {
    echo "📥 Fetching latest Cursor version metadata..."
    JSON=$(curl -sL "$DOWNLOAD_API")
    VERSION=$(echo "$JSON" | grep -oP '"version":"\K[^"]+')
    FILE_URL=$(echo "$JSON" | grep -oP '"downloadUrl":"\K[^"]+')

    if [[ -z "$FILE_URL" || -z "$VERSION" ]]; then
        echo "❌ Failed to fetch Cursor version or download URL."
        exit 1
    fi

    echo "📥 Downloading Cursor v$VERSION..."
    curl -Lo "/tmp/$APPIMAGE_NAME" "$FILE_URL"
}

function install_cursor() {
    echo "🚀 Starting Cursor installation..."

    # Install libfuse2 if missing
    if ! dpkg -s libfuse2 &>/dev/null; then
        echo "📦 Installing libfuse2..."
        sudo apt update
        sudo apt install -y libfuse2
    fi

    # Move AppImage and extract
    sudo mv "/tmp/$APPIMAGE_NAME" "$INSTALL_DIR/"
    cd "$INSTALL_DIR"
    sudo chmod +x "$APPIMAGE_NAME"
    sudo ./"$APPIMAGE_NAME" --appimage-extract

    # Create symlink
    echo "🔗 Linking binary to $SYMLINK"
    sudo ln -sf "$EXTRACTED_DIR/AppRun" "$SYMLINK"

    # Create .desktop file
    echo "🖼️ Creating desktop shortcut..."
    sudo tee "$DESKTOP_ENTRY" > /dev/null <<EOF
[Desktop Entry]
Name=Cursor
Exec=$EXTRACTED_DIR/AppRun
Icon=$EXTRACTED_DIR/usr/share/icons/hicolor/256x256/apps/cursor.png
Type=Application
Categories=Development;Utility;
Terminal=false
EOF

    sudo chmod +x "$EXTRACTED_DIR/AppRun"
    sudo chmod +x "$DESKTOP_ENTRY"

    echo "✅ Cursor installed successfully. Run it with: cursor"
}

function update_cursor() {
    echo "♻️ Updating Cursor..."
    uninstall_cursor false
    download_cursor
    install_cursor
    echo "✅ Cursor updated successfully."
}

function uninstall_cursor() {
    echo "🧹 Uninstalling Cursor..."

    # Remove files
    sudo rm -f "$INSTALL_DIR/$APPIMAGE_NAME"
    sudo rm -rf "$EXTRACTED_DIR"
    sudo rm -f "$SYMLINK"
    sudo rm -f "$DESKTOP_ENTRY"

    if [[ "$1" != "false" ]]; then
        echo "✅ Cursor uninstalled successfully."
    fi
}

function show_menu() {
    echo "============================"
    echo " Cursor Installer for Ubuntu"
    echo "============================"
    echo "1) Install Cursor"
    echo "2) Update Cursor"
    echo "3) Uninstall Cursor"
    echo "4) Exit"
    echo
    read -rp "Choose an option [1-4]: " CHOICE

    case "$CHOICE" in
        1)
            download_cursor
            install_cursor
            ;;
        2)
            update_cursor
            ;;
        3)
            uninstall_cursor true
            ;;
        4)
            echo "👋 Exiting."
            exit 0
            ;;
        *)
            echo "❌ Invalid option. Please try again."
            show_menu
            ;;
    esac
}

# Run the menu
show_menu

3. Make this script executable

chmod +x ~/cursor.sh

4. Now just run the script, choose the option as required.

~/./cursor.sh