Install on Ubuntu Latest without Fuse

I and Claude created this to run without Fuse.

Requires you download the latest AppImage into ~/Downloads

I have AppArmor disabled.

Comments and improvements welcome.

#!/bin/bash

echo "Home: ${HOME}"

# Set a valid working directory to avoid getcwd errors
cd ${HOME}/Applications || {
    echo "Error: Cannot change to ~/Applications."
    exit 1
}

# Ensure ~/Downloads exists
if [ ! -d "${HOME}/Downloads" ]; then
    echo "Error: ~/Downloads directory does not exist."
    exit 1
fi

# Find the latest Cursor AppImage in ~/Downloads
FILES=~/Downloads/Cursor*.AppImage
COUNT=$(ls -1 $FILES 2>/dev/null | wc -l)

if [ "$COUNT" -eq 0 ]; then
    echo "Error: No file matching Cursor*.AppImage found in ~/Downloads."
    exit 1
elif [ "$COUNT" -gt 1 ]; then
    echo "Error: Multiple files matching Cursor*.AppImage found."
    exit 1
fi

# Get the single matching file
LATEST_CURSOR=$(ls -1 ~/Downloads/Cursor-*.AppImage | sort -V | tail -n 1)
echo "Latest Cursor: $LATEST_CURSOR"

# Extract filename and version
FILE_NAME=$(basename "${LATEST_CURSOR}")
echo "File name: ${FILE_NAME}"
BASE_NAME=$(basename "${LATEST_CURSOR}" .AppImage)
echo "Cursor Version: ${BASE_NAME}"

# Copy to ~/Applications
mkdir -p ~/Applications
mv "$LATEST_CURSOR" ~/Applications/ || {
    echo "Error: Failed to move $LATEST_CURSOR to ~/Applications."
    exit 1
}
# Verify the copied file
LATEST_CURSOR=~/Applications/${FILE_NAME}

if [ ! -f "$LATEST_CURSOR" ]; then 
    echo "Error: $LATEST_CURSOR not found after copy."
    exit 1
fi
echo "Latest Cursor: $LATEST_CURSOR"

# Extract AppImage (assumes no FUSE required)
chmod +x "$LATEST_CURSOR"
"$LATEST_CURSOR" --appimage-extract || {
    echo "Error: Failed to extract $LATEST_CURSOR. Ensure FUSE is installed."
    exit 1
}
chmod +x ~/Applications/Cursor.AppImage

# Move extracted files
sudo rm -fr ~/.local/bin/cursor
mkdir -p ~/.local/bin/cursor
mv -f squashfs-root/* ~/.local/bin/cursor/ || {
    echo "Error: Failed to move extracted files to ~/.local/bin/cursor."
    exit 1
}

# Set chrome-sandbox permissions
sudo chown root:root ~/.local/bin/cursor/usr/share/cursor/chrome-sandbox
sudo chmod 4755 ~/.local/bin/cursor/usr/share/cursor/chrome-sandbox
CURSOR_EXEC="$HOME/.local/bin/cursor/AppRun"

# Create desktop entry
mkdir -p ~/.local/share/applications
cat > ~/.local/share/applications/cursor.desktop << EOF
[Desktop Entry]
Name=Cursor
Exec=env LD_LIBRARY_PATH=$HOME/.local/bin/cursor/usr/lib:\$LD_LIBRARY_PATH $CURSOR_EXEC
Icon=utilities-terminal
Type=Application
Categories=Development;
EOF
echo "Updated cursor.desktop with $CURSOR_EXEC"

# Update local desktop database
update-desktop-database ~/.local/share/applications || {
    echo "Warning: Failed to update desktop database for ~/.local/share/applications"
}

# Download custom icon if missing
ICON_PATH="$HOME/.local/share/icons/cursor.png"
if [ ! -f "$ICON_PATH" ]; then
    mkdir -p ~/.local/share/icons
    wget -O "$ICON_PATH" https://registry.npmmirror.com/@lobehub/icons-static-png/latest/files/dark/cursor.png || {
        echo "Warning: Failed to download Cursor icon"
    }
fi
echo "Icon added to: ${ICON_PATH}"

# Update desktop file with custom icon
if [ -f "$ICON_PATH" ]; then
    sed -i "s|Icon=utilities-terminal|Icon=$ICON_PATH|" ~/.local/share/applications/cursor.desktop
    echo "Updated desktop entry with custom icon"
    update-desktop-database ~/.local/share/applications || {
        echo "Warning: Failed to update desktop database for icon change"
    }
fi

echo "Cursor desktop entry update complete."
exit 0