Skip to content

Commit 08c87eb

Browse files
ZanzyTHEbarwatzonCopilotCopilot
authored
Fix: Cursor .desktop file not registering a schema handler for xdg-open, thus not supporting magic link (#17)
* fix: download cursor app image - Cursor changed their download link behaviour and now how a dynamic HTML page. These changes use HTML scraping instead of jq to grab the download link - Refactor download info retrieval in cursor.shfix: * Update cursor script URL in install.sh - temporary switch to point to my cursor installer script * fix: FUSE installation and improve AppImage handling - Updated FUSE installation checks and improved error handling. - Enhanced architecture verification for the Cursor AppImage and added safeguards for execution permissions. - Ensured that the right binary version is downloaded * chore: Update cursor script URL in install.sh - revert to offcial link for pr * Update cursor.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Initial plan * Fix .desktop file format for xdg-open and backlinks support Co-authored-by: ZanzyTHEbar <45744329+ZanzyTHEbar@users.noreply.github.com> * fix: Update cursor.sh to escape proper quotations Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: update cursor.sh to ensure proper file handling with fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: Update cursor.sh properly handle special characters in %U with sed Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * chore: Update install script URL to point to my own repository location for personal testing and usage * chore: Update installation script URLs to point to personal repository for testing * refactor: Simplify variable assignments in cursor.sh and uninstall.sh for improved readability * feat: Add extracted installation mode for Cursor, allowing FUSE-free operation - Introduced INSTALL_MODE variable to toggle between AppImage and extracted modes. - Implemented functions to handle extracted installations, including downloading, extracting, and creating launcher scripts. - Updated installation and README scripts to support the new mode, enhancing usability for environments without FUSE support. * enhance: Improve FUSE installation checks and user feedback in cursor.sh - Added interactive checks for FUSE installation, providing warnings and installation prompts based on terminal interactivity. - Updated README to inform users about FUSE2 requirements and installation instructions. - Refined error handling to ensure the script continues gracefully in non-interactive environments. * feat: Enhance logging and user feedback across installation scripts - Introduced color-coded logging functions in cursor.sh and install.sh for improved user experience. - Updated installation and uninstallation scripts to utilize logging functions for better visibility of actions and errors. - Refined README to reflect changes in installation methods and provide clearer instructions for users. - Added pre-push hook and CI workflow to enforce canonical links and maintain repository integrity. * chore: Update uninstall script URLs in README to reflect new repository location * fix: broken url and version parsing in fallback cursor.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: With set -e, find returning non-zero for non-existent dirs can abort the script. Guard the find with a directory check and neutralize non-zero status in uninstall.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: Running find on a non-existent icon root will return non-zero under set -e and can terminate the script. Add a directory existence check or tolerate non-zero exit Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: Enhance uninstall script to improve icon removal and cleanup - Updated icon removal logic to delete all 'cursor' and legacy 'co.anysphere.cursor' icons under the hicolor theme. - Added cleanup for now-empty directories in the icon path. - Included a step to refresh the desktop database for improved menu visibility. - Implemented removal of extracted installation directories and related metadata. * fix: bug in .desktop file creation where sed created a quoted Exec directive, causing it to fail silently - Add desktop file reinstallation functionality - Introduced a new function to reinstall the Cursor desktop file, allowing users to refresh the desktop entry easily. - Updated the Exec command in the desktop file to remove quotes for better compatibility. - Enhanced error handling for missing desktop files and added logic to create a minimal desktop entry if extraction fails. - Ensured the desktop file is updated with the correct icon and MIME type support. - Added a new command-line option `--reinstall-desktop` for triggering the reinstallation process. * Fix icon install when hicolor symlinks are broken * fix: avoid cursor CLI conflict Rename the installer CLI to cursor-installer and update docs. Source shared lib.sh in scripts and install it alongside the CLI. * fix: centralize safe removal helpers Move safe_remove and validate_path into lib.sh and reuse them where installer-managed files are removed. * refactor: share appimage lookup helper Move find_cursor_appimage into lib.sh and reuse it in installer and uninstall scripts. --------- Co-authored-by: Chris Watson <cawatson1993@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 5ac1ee9 commit 08c87eb

8 files changed

Lines changed: 1155 additions & 181 deletions

File tree

.githooks/pre-push

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Git pre-push hook: enforce canonical links only when pushing local main
6+
# Canonical target: watzon/cursor-linux-installer@main
7+
8+
# Read remote name/url provided by git
9+
remote_name=${1:-}
10+
remote_url=${2:-}
11+
12+
should_check=false
13+
main_local_sha=""
14+
main_remote_sha=""
15+
while read -r local_ref local_sha remote_ref remote_sha; do
16+
if [ "$local_ref" = "refs/heads/main" ] || [ "$remote_ref" = "refs/heads/main" ]; then
17+
should_check=true
18+
main_local_sha="$local_sha"
19+
main_remote_sha="$remote_sha"
20+
break
21+
fi
22+
done
23+
24+
if [ "$should_check" = true ]; then
25+
echo "pre-push: enforcing canonical links for main (remote=$remote_name url=$remote_url local_sha=$main_local_sha remote_sha=$main_remote_sha)..."
26+
hook_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
27+
bash "$hook_dir/../scripts/check-links.sh"
28+
fi
29+
30+
exit 0
31+
32+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Enforce Canonical Links
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
check:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Make scripts executable
17+
run: |
18+
chmod +x scripts/check-links.sh || true
19+
20+
- name: Verify canonical links and defaults
21+
run: |
22+
bash scripts/check-links.sh

README.md

Lines changed: 143 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,104 @@ Cursor is an excellent AI-powered code editor, but it doesn't treat Linux as a f
55
This repository aims to solve that problem by providing a set of shell scripts that will:
66

77
1. Download and install Cursor for you
8-
2. Provide a `cursor` command that you can run from your shell
8+
2. Provide a `cursor-installer` command that you can run from your shell
99
3. Allow you to easily update Cursor when new versions are released
1010

1111
## Installation
1212

13-
You can install the Cursor Linux Installer using either curl or wget. Choose the method you prefer:
13+
There are two ways to install, depending on whether you want to run from the GitHub one-liner or from a locally cloned repository.
1414

15-
### Using curl
15+
### Method 1: One‑liner (curl)
1616

1717
```bash
18-
# Install stable version (default)
18+
# Install stable version (default, AppImage mode)
1919
curl -fsSL https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash
2020

2121
# Install latest version
2222
curl -fsSL https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash -s -- latest
23+
24+
# Install in extracted mode (no FUSE required)
25+
curl -fsSL https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash -s -- stable --extract
2326
```
2427

25-
### Using wget
28+
### Method 1: One‑liner (wget)
2629

2730
```bash
28-
# Install stable version (default)
31+
# Install stable version (default, AppImage mode)
2932
wget -qO- https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash
3033

3134
# Install latest version
3235
wget -qO- https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash -s -- latest
36+
37+
# Install in extracted mode (no FUSE required)
38+
wget -qO- https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash -s -- stable --extract
39+
```
40+
41+
The one‑liner script will:
42+
43+
1. Download the `cursor.sh` script and save it as `cursor-installer` in `~/.local/bin/`
44+
2. Download `lib.sh` to `~/.local/share/cursor-installer/lib.sh`
45+
3. Make the script executable
46+
4. Download and install the latest version of Cursor
47+
48+
**Note:** If you're installing via the piped bash method and don't have FUSE2 installed, the script will warn you but continue. You'll need to either:
49+
50+
- Install FUSE2 manually: `sudo apt-get install libfuse2` (Debian/Ubuntu), `sudo dnf install fuse` (Fedora), or `sudo pacman -S fuse2` (Arch)
51+
- Use extracted mode: `curl -fsSL https://raw.githubusercontent.com/watzon/cursor-linux-installer/main/install.sh | bash -s -- stable --extract`
52+
53+
### Method 2: Local clone
54+
55+
```bash
56+
git clone https://github.com/watzon/cursor-linux-installer.git
57+
cd cursor-linux-installer
58+
59+
# AppImage mode (default)
60+
./install.sh stable
61+
62+
# Latest release
63+
./install.sh latest
64+
65+
# Extracted, no-FUSE mode
66+
./install.sh latest --extract
3367
```
3468

35-
The installation script will:
69+
When you run `./install.sh` from the repo, it uses the local `cursor.sh` and `lib.sh` instead of downloading from GitHub.
70+
71+
### Maintainers: Switching between personal and canonical repos
72+
73+
This fork uses a personal branch for development and the upstream repo for canonical links. The installer supports environment overrides so you can test personal builds without modifying repo defaults:
74+
75+
```bash
76+
# (Optional) Personal testing without editing repo defaults
77+
export REPO_OWNER="ZanzyTHEbar"
78+
export REPO_BRANCH="personal"
79+
./install.sh latest
80+
```
81+
82+
CI or release scripts can set these env vars to ensure links point to the canonical repo in artifacts and docs.
83+
84+
#### Branch protection and automation
85+
86+
This repository enforces that `main` always points to the canonical upstream (`watzon/cursor-linux-installer`).
87+
88+
- A GitHub Action (`.github/workflows/enforce-canonical.yml`) runs on pushes and PRs to `main` and fails if:
89+
- Any personal links like `ZanzyTHEbar/cursor-linux-installer/personal` are present in tracked files.
90+
- `install.sh` defaults are not `REPO_OWNER=watzon` and `REPO_BRANCH=main`.
91+
92+
Maintainer workflow:
93+
94+
1. Develop on personal branch.
95+
2. Merge to `main` in your fork.
96+
3. Canonical defaults are used automatically (`watzon/main`). For personal testing, use the env overrides shown above.
97+
98+
4. Enable local git hook to prevent pushing non-canonical links to main:
99+
100+
```bash
101+
git config core.hooksPath .githooks
102+
chmod +x .githooks/pre-push
103+
```
36104

37-
1. Download the `cursor.sh` script and save it as `cursor` in `~/.local/bin/`
38-
2. Make the script executable
39-
3. Download and install the latest version of Cursor
105+
5. Open PR to upstream. CI will verify canonical links.
40106

41107
## Uninstalling
42108

@@ -55,23 +121,81 @@ bash -c "$(wget -qO- https://raw.githubusercontent.com/watzon/cursor-linux-insta
55121

56122
The uninstall script will:
57123

58-
1. Remove the `cursor` script from `~/.local/bin/`
59-
2. Remove the Cursor AppImage
60-
3. Ask if you want to remove the Cursor configuration files
124+
1. Remove the `cursor-installer` script from `~/.local/bin/`
125+
2. Remove the shared `lib.sh` from `~/.local/share/cursor-installer/`
126+
3. Remove the Cursor AppImage
127+
4. Ask if you want to remove the Cursor configuration files
61128

62129
## Usage
63130

64-
After installation, you can use the `cursor` command to launch Cursor or update it:
131+
Note: The installer CLI is `cursor-installer` to avoid conflicts with Cursor's official `cursor` CLI.
65132

66-
- To launch Cursor: `cursor`
67-
- To update Cursor: `cursor --update [options]`
68-
- Update to stable version: `cursor --update` or `cursor --update stable`
69-
- Update to latest version: `cursor --update latest`
133+
After installation, you can use the `cursor-installer` command to launch Cursor or update it:
134+
135+
- To launch Cursor: `cursor-installer`
136+
- To update Cursor: `cursor-installer --update [options]`
137+
- Update to stable version: `cursor-installer --update` or `cursor-installer --update stable`
138+
- Update to latest version: `cursor-installer --update latest`
70139
- Additional arguments can be passed after `--update` to control the update behavior
71-
- To check Cursor version: `cursor --version` or `cursor -v`
140+
- To check available versions: `cursor-installer --check` or `cursor-installer -c`
141+
- To check Cursor version: `cursor-installer --version` or `cursor-installer -v`
72142
- Shows the installed version of Cursor if available
73143
- Returns an error if Cursor is not installed or version cannot be determined
74144

145+
## Installation Modes
146+
147+
The installer supports two installation modes:
148+
149+
### AppImage Mode (Default)
150+
151+
The default mode installs Cursor as an AppImage. This requires FUSE2 to be installed on your system.
152+
153+
**Requirements:**
154+
155+
- FUSE2 (automatically installed by the script on Debian/Ubuntu, Fedora, and Arch)
156+
157+
**Advantages:**
158+
159+
- Smaller disk footprint
160+
- Standard AppImage format
161+
162+
**Usage:**
163+
164+
```bash
165+
cursor-installer --update stable
166+
```
167+
168+
### Extracted Mode (FUSE-Free)
169+
170+
This mode fully extracts the AppImage and installs Cursor as a native application, **eliminating the need for FUSE**. This is ideal for:
171+
172+
- Systems without FUSE support
173+
- Restricted environments (containers, some cloud instances)
174+
- Users who prefer traditional installations
175+
176+
**Advantages:**
177+
178+
- No FUSE dependency
179+
- Works in restricted environments
180+
- Native application structure
181+
- Potentially better compatibility
182+
183+
**Usage:**
184+
185+
```bash
186+
# Install in extracted mode
187+
cursor-installer --extract
188+
189+
# Update in extracted mode
190+
cursor-installer --extract --update stable
191+
192+
# Set as default via environment variable
193+
export CURSOR_INSTALL_MODE=extracted
194+
cursor-installer --update stable
195+
```
196+
197+
**Note:** The extracted installation is stored in `~/.local/share/cursor/`.
198+
75199
## Note
76200

77201
If you encounter a warning that `~/.local/bin` is not in your PATH, you can add it by running:

0 commit comments

Comments
 (0)