I downloaded the cursor*.AppImage file and run it to open the editor. Will it auto-update? If not, how do I set it up?
Hi @evgenyneu
Here’s some information on how to enable updates in Linux.
Seems that cursor does not prioritize linux users so all updates are delayed, missing, and not integrated with the OS. This led me to windsurf which is also a vscode fork but native for linux.
Check out a thread about this issue: Please improve Linux support
Well these instructions did not work. Appreciate the effort though. It is shameful that the Cursor team cannot develop a proper install/update process for Cursor in Linux.
It works but needed a small tweak in the update-cursor.sh script, the url used in the tutorial doesn’t work anymore so replaced it with the new url and the new url doesn’t directly give you the AppImage, it returns a JSON with the actual download URL inside it. So I had to update the script to first fetch that URL using. Also, make sure both are installed (sudo apt install curl jq if needed).
#!/bin/bash
APPDIR=~/Applications/cursor
APPIMAGE_URL_API="https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable"
# Create the app directory if it doesn't exist
mkdir -p "$APPDIR"
# Fetch the actual AppImage URL from the API
echo "Fetching latest Cursor AppImage URL..."
DOWNLOAD_URL=$(curl -s "$APPIMAGE_URL_API" | jq -r '.downloadUrl')
# Check if we got a valid URL
if [[ -z "$DOWNLOAD_URL" || "$DOWNLOAD_URL" == "null" ]]; then
echo "Error: Failed to retrieve download URL from Cursor API."
exit 1
fi
# Download and make it executable
echo "Downloading Cursor AppImage from $DOWNLOAD_URL..."
wget -O "$APPDIR/cursor.AppImage" "$DOWNLOAD_URL"
chmod +x "$APPDIR/cursor.AppImage"
echo "Cursor AppImage installed at $APPDIR/cursor.AppImage"
This is great - I made some adjustments to follow the redirect from cursor as well as check the version instead of downloading the newest image every time regardless of updates, if any interest.
#!/bin/bash
APPDIR=~/Applications/cursor
APPIMAGE_URL_API="https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable"
VERSION_FILE="$APPDIR/current_version.txt"
# Create the app directory if it doesn't exist
mkdir -p "$APPDIR"
echo "Checking for Cursor updates..."
# Fetch the latest release info from the API
API_RESPONSE=$(curl -sL --connect-timeout 30 --max-time 60 "$APPIMAGE_URL_API")
if [ $? -ne 0 ] || [ -z "$API_RESPONSE" ]; then
echo "Error: Failed to connect to Cursor API."
exit 1
fi
# Extract download URL and version info
DOWNLOAD_URL=$(echo "$API_RESPONSE" | jq -r '.downloadUrl' 2>/dev/null)
LATEST_VERSION=$(echo "$API_RESPONSE" | jq -r '.version // .tag_name // "unknown"' 2>/dev/null)
if [[ -z "$DOWNLOAD_URL" || "$DOWNLOAD_URL" == "null" ]]; then
echo "Error: Failed to retrieve download URL from Cursor API."
exit 1
fi
# If we can't get version info from API, use URL as version identifier
if [[ -z "$LATEST_VERSION" || "$LATEST_VERSION" == "null" || "$LATEST_VERSION" == "unknown" ]]; then
LATEST_VERSION=$(echo "$DOWNLOAD_URL" | grep -o '/[^/]*\.AppImage' | sed 's|/||' | sed 's|\.AppImage||')
fi
echo "Latest version: $LATEST_VERSION"
# Check current version
CURRENT_VERSION=""
if [ -f "$VERSION_FILE" ]; then
CURRENT_VERSION=$(cat "$VERSION_FILE")
echo "Current version: $CURRENT_VERSION"
fi
# Check if we need to update
if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ] && [ -f "$APPDIR/cursor.AppImage" ]; then
echo "Cursor is already up to date (version: $CURRENT_VERSION)"
exit 0
fi
echo "New version available! Updating from '$CURRENT_VERSION' to '$LATEST_VERSION'"
# Download the new version
echo "Downloading Cursor AppImage from $DOWNLOAD_URL..."
if curl -L --fail --progress-bar -o "$APPDIR/cursor.AppImage.tmp" "$DOWNLOAD_URL"; then
if [ -s "$APPDIR/cursor.AppImage.tmp" ]; then
# Backup old version if it exists
if [ -f "$APPDIR/cursor.AppImage" ]; then
mv "$APPDIR/cursor.AppImage" "$APPDIR/cursor.AppImage.backup"
fi
# Install new version
mv "$APPDIR/cursor.AppImage.tmp" "$APPDIR/cursor.AppImage"
chmod +x "$APPDIR/cursor.AppImage"
# Save version info
echo "$LATEST_VERSION" > "$VERSION_FILE"
echo "✅ Cursor successfully updated to version $LATEST_VERSION"
echo "File size: $(ls -lh "$APPDIR/cursor.AppImage" | awk '{print $5}')"
# Clean up backup after successful update
rm -f "$APPDIR/cursor.AppImage.backup"
else
echo "Error: Downloaded file is empty"
rm -f "$APPDIR/cursor.AppImage.tmp"
exit 1
fi
else
echo "Error: Failed to download Cursor AppImage"
rm -f "$APPDIR/cursor.AppImage.tmp"
exit 1
fi
Updated install-cursor.sh
#!/bin/bash
set -euo pipefail
# --- Config ---
API_URL="https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable"
ICON_URL="https://avatars.githubusercontent.com/u/126759922"
INSTALL_DIR="$HOME/Applications/cursor"
CURSOR_APP_IMAGE="$INSTALL_DIR/cursor.AppImage"
CURSOR_ICON="$INSTALL_DIR/cursor-icon.png"
DESKTOP_FILE="$HOME/.local/share/applications/cursor.desktop"
WRAPPER_SYS="/usr/local/bin/cursor"
WRAPPER_USER="$HOME/.local/bin/cursor"
# --- Helpers ---
need_cmd() {
command -v "$1" >/dev/null 2>&1 || { echo "Missing dependency: $1" >&2; exit 1; }
}
# --- Checks ---
need_cmd curl
need_cmd jq
need_cmd wget
# --- Fetch latest download URL ---
echo "Fetching latest Cursor release info..."
json=$(curl -fsSL "$API_URL")
download_url=$(echo "$json" | jq -r '.downloadUrl')
if [[ -z "$download_url" || "$download_url" == "null" ]]; then
echo "Failed to retrieve downloadUrl from API: $API_URL" >&2
exit 1
fi
# --- Prepare directories ---
mkdir -p "$INSTALL_DIR"
# --- Download AppImage ---
echo "Downloading Cursor AppImage from:"
echo " $download_url"
# show a progress bar; follow redirects if any
wget --progress=bar:force:noscroll -O "$CURSOR_APP_IMAGE" "$download_url"
chmod +x "$CURSOR_APP_IMAGE"
echo "✔ AppImage saved to $CURSOR_APP_IMAGE"
# --- Create launcher wrapper that adds --no-sandbox ---
create_wrapper() {
local path="$1"
mkdir -p "$(dirname "$path")"
cat > "$path" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
APPIMAGE_PATH="__APPIMAGE_PATH__"
exec "$APPIMAGE_PATH" --no-sandbox "$@"
EOF
# Inject the real AppImage path safely
sed -i "s#__APPIMAGE_PATH__#$(printf '%q' "$CURSOR_APP_IMAGE")#g" "$path"
chmod +x "$path"
}
EXEC_PATH=""
if sudo -n true 2>/dev/null; then
echo "Creating system-wide wrapper at $WRAPPER_SYS (using sudo)..."
tmpfile="$(mktemp)"
create_wrapper "$tmpfile"
sudo mv "$tmpfile" "$WRAPPER_SYS"
EXEC_PATH="$WRAPPER_SYS"
else
echo "No passwordless sudo detected. Attempting sudo for system-wide wrapper..."
if sudo true; then
echo "Creating system-wide wrapper at $WRAPPER_SYS..."
tmpfile="$(mktemp)"
create_wrapper "$tmpfile"
sudo mv "$tmpfile" "$WRAPPER_SYS"
EXEC_PATH="$WRAPPER_SYS"
else
echo "Falling back to user wrapper at $WRAPPER_USER"
create_wrapper "$WRAPPER_USER"
EXEC_PATH="$WRAPPER_USER"
fi
fi
echo "✔ Wrapper created at $EXEC_PATH (adds --no-sandbox)"
# --- Download icon (best-effort) ---
echo "Fetching icon..."
wget -q -O "$CURSOR_ICON" "$ICON_URL" || echo "Icon download failed; continuing."
# --- Create .desktop entry ---
mkdir -p "$(dirname "$DESKTOP_FILE")"
cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Name=Cursor
Exec=$EXEC_PATH %U
TryExec=$EXEC_PATH
Icon=$CURSOR_ICON
Type=Application
Categories=Utility;Development;
Terminal=false
StartupNotify=true
EOF
echo "✔ Desktop entry created at $DESKTOP_FILE"
# --- Refresh desktop database / menus (best-effort) ---
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database "$HOME/.local/share/applications" || true
fi
if command -v xdg-desktop-menu >/dev/null 2>&1; then
xdg-desktop-menu forceupdate || true
fi
echo
echo "✅ Cursor installed."
echo " AppImage: $CURSOR_APP_IMAGE"
echo " Launcher: $EXEC_PATH (always runs with --no-sandbox)"
echo " Menu entry: $DESKTOP_FILE"
echo
echo "You should now find 'Cursor' in your applications menu."
echo "Or run: $(printf '%q' "$EXEC_PATH")"
Updated update-cursor.sh
#!/bin/bash
set -euo pipefail
API_URL="https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable"
INSTALL_DIR="$HOME/Applications/cursor"
CURSOR_APP_IMAGE="$INSTALL_DIR/cursor.AppImage"
# Check dependencies
for cmd in curl jq wget; do
command -v "$cmd" >/dev/null 2>&1 || {
echo "Missing required command: $cmd" >&2
exit 1
}
done
# Fetch latest release info
echo "Checking for updates..."
json=$(curl -fsSL "$API_URL")
download_url=$(echo "$json" | jq -r '.downloadUrl')
version=$(echo "$json" | jq -r '.version')
if [[ -z "$download_url" || "$download_url" == "null" ]]; then
echo "Failed to retrieve download URL from $API_URL" >&2
exit 1
fi
echo "Latest Cursor version: $version"
echo "Downloading from: $download_url"
# Ensure install dir exists
mkdir -p "$INSTALL_DIR"
# Download to a temp file first
tmpfile=$(mktemp)
wget --progress=bar:force:noscroll -O "$tmpfile" "$download_url"
# Replace old AppImage
mv "$tmpfile" "$CURSOR_APP_IMAGE"
chmod +x "$CURSOR_APP_IMAGE"
echo "✔ Cursor updated to version $version"
echo "Executable: $CURSOR_APP_IMAGE"
Native .deb and RPM releases are now available! ![]()
Get it from Downloads | Cursor - The AI Code Editor
don’t blame them. may be they are using Cursor to develop that
The issue has been fixed! Cursor AppImage automatically updates for me.