Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgs/applications/editors/vscode/generic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
useVSCodeRipgrep ? false,
ripgrep,
hasVsceSign ? false,
patchVSCodePath ? true,
}:

stdenv.mkDerivation (
Expand Down Expand Up @@ -262,9 +263,13 @@ stdenv.mkDerivation (
mkdir -p "$out/share/pixmaps"
cp "$out/lib/${libraryName}/resources/app/resources/linux/code.png" "$out/share/pixmaps/${iconName}.png"

''
+ (lib.optionalString patchVSCodePath ''
# Override the previously determined VSCODE_PATH with the one we know to be correct
sed -i "/ELECTRON=/iVSCODE_PATH='$out/lib/${libraryName}'" "$out/bin/${executableName}"
grep -q "VSCODE_PATH='$out/lib/${libraryName}'" "$out/bin/${executableName}" # check if sed succeeded
'')
+ ''

# Remove native encryption code, as it derives the key from the executable path which does not work for us.
# The credentials should be stored in a secure keychain already, so the benefit of this is questionable
Expand Down
208 changes: 60 additions & 148 deletions pkgs/by-name/co/code-cursor/package.nix
Original file line number Diff line number Diff line change
@@ -1,57 +1,18 @@
{
lib,
stdenvNoCC,
stdenv,
callPackage,
vscode-generic,
fetchurl,

# build
appimageTools,

# linux dependencies
alsa-lib,
at-spi2-atk,
autoPatchelfHook,
cairo,
cups,
curlWithGnuTls,
egl-wayland,
expat,
fontconfig,
freetype,
ffmpeg,
glib,
glibc,
glibcLocales,
gtk3,
libappindicator-gtk3,
libdrm,
libgbm,
libGL,
libnotify,
libva-minimal,
libxkbcommon,
libxkbfile,
makeWrapper,
nspr,
nss,
pango,
pciutils,
pulseaudio,
vivaldi-ffmpeg-codecs,
vulkan-loader,
wayland,

# linux installation
rsync,
commandLineArgs ? "",

# darwin build
undmg,
commandLineArgs ? "",
useVSCodeRipgrep ? stdenv.hostPlatform.isDarwin,
}:
let
pname = "cursor";
version = "1.0.0";
Comment on lines 50 to 52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave these in the let block so the updater can see them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are talking about the update.sh script, I believe I tested the update functionality and it worked fine. The version is extracted from the Nix package attribute:

currentVersion=$(nix-instantiate --eval -E "with import ./. {}; code-cursor.version or (lib.getVersion code-cursor)" | tr -d '"')


inherit (stdenvNoCC) hostPlatform;
let
inherit (stdenv) hostPlatform;
finalCommandLineArgs = "--update=false " + commandLineArgs;

sources = {
x86_64-linux = fetchurl {
Expand All @@ -73,115 +34,47 @@ let
};

source = sources.${hostPlatform.system};

# Linux -- build from AppImage
appimageContents = appimageTools.extractType2 {
inherit version pname;
src = source;
};

wrappedAppimage = appimageTools.wrapType2 {
inherit version pname;
src = source;
};

in
stdenvNoCC.mkDerivation {
inherit pname version;

src = if hostPlatform.isLinux then wrappedAppimage else source;

nativeBuildInputs =
lib.optionals hostPlatform.isLinux [
autoPatchelfHook
glibcLocales
makeWrapper
rsync
]
++ lib.optionals hostPlatform.isDarwin [ undmg ];

buildInputs = lib.optionals hostPlatform.isLinux [
alsa-lib
at-spi2-atk
cairo
cups
curlWithGnuTls
egl-wayland
expat
ffmpeg
glib
gtk3
libdrm
libgbm
libGL
libva-minimal
libxkbcommon
libxkbfile
nspr
nss
pango
pulseaudio
vivaldi-ffmpeg-codecs
vulkan-loader
wayland
];
(callPackage vscode-generic rec {
inherit useVSCodeRipgrep;
commandLineArgs = finalCommandLineArgs;

runtimeDependencies = lib.optionals hostPlatform.isLinux [
egl-wayland
ffmpeg
glibc
libappindicator-gtk3
libnotify
libxkbfile
pciutils
pulseaudio
wayland
fontconfig
freetype
];

sourceRoot = lib.optionalString hostPlatform.isDarwin ".";

# Don't break code signing
dontUpdateAutotoolsGnuConfigScripts = hostPlatform.isDarwin;
dontConfigure = hostPlatform.isDarwin;
dontFixup = hostPlatform.isDarwin;
version = "1.0.0";
pname = "cursor";

installPhase = ''
runHook preInstall
mkdir -p $out/
# You can find the current VSCode version in the About dialog:
# workbench.action.showAboutDialog (Help: About)
vscodeVersion = "1.96.2";

${lib.optionalString hostPlatform.isLinux ''
cp -r bin $out/bin
# mkdir -p $out/share/cursor
# cp -ar ${appimageContents}/usr/share $out/
executableName = "cursor";
longName = "Cursor";
shortName = "cursor";
libraryName = "cursor";
iconName = "cursor";

rsync -a -q ${appimageContents}/usr/share $out/ --exclude "*.so"
src =
if hostPlatform.isLinux then
appimageTools.extract {
inherit pname version;
src = source;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to test on Darwin as well. At the moment, this just doesn't build:

unpacking source archive /nix/store/f2fzrq3g5d2sls18v14hl6m3ciahzkkm-Cursor-darwin-arm64.dmg
do not know how to unpack source archive /nix/store/f2fzrq3g5d2sls18v14hl6m3ciahzkkm-Cursor-darwin-arm64.dmg
error: builder for '/nix/store/wykkg96bg07105f1dwacwr2xcpl9q3vw-cursor-1.0.0.drv' failed with exit code 1;
       last 3 log lines:
       > Running phase: unpackPhase
       > unpacking source archive /nix/store/f2fzrq3g5d2sls18v14hl6m3ciahzkkm-Cursor-darwin-arm64.dmg
       > do not know how to unpack source archive /nix/store/f2fzrq3g5d2sls18v14hl6m3ciahzkkm-Cursor-darwin-arm64.dmg
       For full logs, run:
         nix log /nix/store/wykkg96bg07105f1dwacwr2xcpl9q3vw-cursor-1.0.0.drv

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a starting point: AppImage and dmg are different formats and use different unpacking tools -- appImageTools.extract vs. undmg. The underlying structure is different too.

Please mark this PR as a draft while you work this out.

Copy link
Member Author

@Zaczero Zaczero Jun 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I test it on Darwin easily? I only have a Linux machine - is there a good way (like emulation)? A simple test suite would be ok? (GitHub runners will be able to run them). I'll see what I can do about this Darwin situation, but not today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need access to an Apple machine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option is to keep the Apple build as it is and only alter the Linux build.

Copy link
Member Author

@Zaczero Zaczero Jun 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have specified vscodeVersion that guides the generic builder on how to work with the unpacked code. This affects this conditional that caused the ripgrep patch failure:

vscodeRipgrep =
  if stdenv.hostPlatform.isDarwin then
    if lib.versionAtLeast vscodeVersion "1.94.0" then
      "Contents/Resources/app/node_modules/@vscode/ripgrep/bin/rg"
    else
      "Contents/Resources/app/node_modules.asar.unpacked/@vscode/ripgrep/bin/rg"
  else
    "resources/app/node_modules/@vscode/ripgrep/bin/rg";

https://github.com/NixOS/nixpkgs/compare/994a8c0869e6b815149eebad32f2e6c1b1f4ada3..8f156e3a5c4df23218c2ebffd9e4ba8735a4e0e7

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Zaczero this fixes the build on Darwin. Thank you.

How are you testing this on linux?

Copy link
Member

@JohnRTitor JohnRTitor Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I test it on Darwin easily? I only have a Linux machine

GitHub runners can provide a build environment but you can't run cursor there obviously. Nix Community provides a darwin builder too, but no GUI access, sadly.

My suggestion would be to wait until you finish your work for the Linux package. Then someone with access to a darwin machine (@sarahec) can clone your branch, make and test the changes needed, then send a PR to your branch or send you their patch file, which you can then apply to your branch.

Once it all works, we can merge.

Copy link
Contributor

@sarahec sarahec Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: the vscode version, is there a way to detect it from the unpacked sources? I'm thinking of the maintenance burden on upgrade. Autodetection lets us continue to use the upgrade script.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you testing this on linux?

In my configuration.nix, I import the package from the fork directory and then add it to my user packages. This also has the benefit of my being quickly able to run the latest code-cursor without waiting for upstream updates by doing them myself.

code-cursor' = pkgs.callPackage .../vscode/cursor.nix { };

GitHub runners can provide a build environment

I think this is the best fallback option. Luckily, this package is popular enough that there are real people with Darwin machines to test it. The beauty of an open-source community.

re: the vscode version, is there a way to detect it from the unpacked sources? I'm thinking of the maintenance burden on upgrade.

I don't know, but I also don't see it as a maintenance burden. The generic builder only has 1 version conditional that is quite loose. So far, Cursor has received about 2 base VSCode updates per year. Even if it's not up to date, it won't really matter. I have checked how Windsurf does that, and apparently they provide the VSCode version via the update API; Cursor does not.

}
else
source;

# Fix the desktop file to point to the correct location
substituteInPlace $out/share/applications/cursor.desktop --replace-fail "/usr/share/cursor/cursor" "$out/bin/cursor"
sourceRoot =
if hostPlatform.isLinux then "${pname}-${version}-extracted/usr/share/cursor" else "Cursor.app";

wrapProgram $out/bin/cursor \
--add-flags "--update=false" \
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}} --no-update" \
--add-flags ${lib.escapeShellArg commandLineArgs}
''}
tests = { };

${lib.optionalString hostPlatform.isDarwin ''
APP_DIR="$out/Applications"
mkdir -p "$APP_DIR"
cp -Rp Cursor.app "$APP_DIR"
mkdir -p "$out/bin"
ln -s "$APP_DIR/Cursor.app/Contents/Resources/app/bin/cursor" "$out/bin/cursor"
''}
updateScript = ./update.sh;

runHook postInstall
'';
# Editing the `cursor` binary within the app bundle causes the bundle's signature
# to be invalidated, which prevents launching starting with macOS Ventura, because Cursor is notarized.
# See https://eclecticlight.co/2022/06/17/app-security-changes-coming-in-ventura/ for more information.
dontFixup = stdenv.hostPlatform.isDarwin;

passthru = {
inherit sources;
updateScript = ./update.sh;
};
# Cursor has no wrapper script.
patchVSCodePath = false;

meta = {
description = "AI-powered code editor built on vscode";
Expand All @@ -193,7 +86,26 @@ stdenvNoCC.mkDerivation {
aspauldingcode
prince213
];
platforms = lib.platforms.linux ++ lib.platforms.darwin;
platforms = [
"aarch64-linux"
"x86_64-linux"
] ++ lib.platforms.darwin;
mainProgram = "cursor";
};
}
}).overrideAttrs
(oldAttrs: {
nativeBuildInputs =
(oldAttrs.nativeBuildInputs or [ ])
++ lib.optionals hostPlatform.isDarwin [ undmg ];

preInstall =
(oldAttrs.preInstall or "")
+ lib.optionalString hostPlatform.isLinux ''
mkdir -p bin
ln -s ../cursor bin/cursor
'';

passthru = (oldAttrs.passthru or { }) // {
inherit sources;
};
})
6 changes: 6 additions & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14408,6 +14408,12 @@ with pkgs;
vscodium-fhs = vscodium.fhs;
vscodium-fhsWithPackages = vscodium.fhsWithPackages;

code-cursor = callPackage ../by-name/co/code-cursor/package.nix {
vscode-generic = ../applications/editors/vscode/generic.nix;
};
code-cursor-fhs = code-cursor.fhs;
code-cursor-fhsWithPackages = code-cursor.fhsWithPackages;

windsurf = callPackage ../by-name/wi/windsurf/package.nix {
vscode-generic = ../applications/editors/vscode/generic.nix;
};
Expand Down
Loading