LnL7 / nix-darwin

nix modules for darwin
MIT License
3.16k stars 454 forks source link

How to add applications so they show up in Applications (or Launchpad search) #214

Open spease opened 4 years ago

spease commented 4 years ago

It seems if I add applications in the user configuration file, they end up in ~/Applications rather than in the system Applications. I there a way to add packages to the system so the symlinks will show up in the root Applications, or at least will be searchable with Launchpad?

I couldn't find any "Getting Started" documentation with nix-darwin that would answer this question, but I'm very interested in getting more hands-on experience with the nix ecosystem

jsravn commented 4 years ago

@spease It's currently bugged in nix-darwin. There is a workaround at https://github.com/LnL7/nix-darwin/issues/139#issuecomment-666771621. Hopefully it will get a fix soon - it should be easy to make a PR for it.

purcell commented 4 years ago

Note that the linked comment is about making the apps show up in LaunchPad etc., but they still live in ~/Applications. There was other discussion in that issue about the wider question of /Applications vs. ~/Applications, and a corresponding PR was opened (#153) and later abandoned.

spease commented 4 years ago

I’m not as worried about that particular aspect, it’s more having a GUI app behave ergonomically once it’s included in the environment. I’m installing things for my user profile so far, not the system, so it makes sense to me that they show up in ~ instead of /.

LnL7 commented 4 years ago

Yeah, moving the system applications out of the home folder would be good.

wangkev commented 4 years ago

I applied the mentioned patch https://github.com/LnL7/nix-darwin/issues/139#issuecomment-666771621, and can see ~/Applications with the .apps. Spotlight and Launchpad still do not see the apps though. Is that expected? I'm on Catalina if that makes any difference.

what-the-functor commented 4 years ago

I applied the mentioned patch #139 (comment), and can see ~/Applications with the .apps. Spotlight and Launchpad still do not see the apps though. Is that expected? I'm on Catalina if that makes any difference.

Some applications in ~/Applications (my own derivations) are listed in LaunchPad; however to get Emacs.app to show up in LaunchPad, I had to create the alias in /Applications. I think there must be some metadata that is different WRT Emacs.app, as opposed to other application bundles.

webframp commented 3 years ago

I would definitely be in favor of some method for linking system installed GUI apps into /Applications instead of ~/Applications. Finder, Alfred etc can't find symlinks in ~/Applications even if they can be made to show up in Launchpad

leira commented 2 years ago

I have the same issue. There is a symlink of Nix Apps under ~/Applications. In Nix Apps linked folder, there is a Kitty.app symlink. Spotlight doesn't show Kitty.

I did some experiment, it seems the problem is the symlinks. If I copy the Kitty.app file into ~/Applications, it works. Even if I put the Kitty.app symlink in /Applications, Spotlight still doesn't see the app. It seems Spotlight simply doesn't support symlinks.

I'm not sure what is the difference between symlinks and aliases in macOS. But even I tried with aliases, Spotlight doesn't see it either.

IvarWithoutBones commented 2 years ago

Folders symlinked to ~/Applications do not show up in spotlight, and copying them seems like a waste of disk space. Not to mention that it can take a while too if you have a lot of packages.

I found a workaround using APFS aliases, those show up in spotlight and barely take any disk space. Note that aliases dont show up under the "Applications" section of spotlight search, but rather "Other". That makes them have a pretty low priority, so they don't show up as the top option. Might be able to work around that by giving them a tag, which AFAIK moves up their priority.

This is my activation script:

  # Nix-darwin does not link installed applications to the user environment. This means apps will not show up
  # in spotlight, and when launched through the dock they come with a terminal window. This is a workaround.
  # Upstream issue: https://github.com/LnL7/nix-darwin/issues/214
  system.activationScripts.applications.text = lib.mkForce ''
    echo "setting up ~/Applications..." >&2
    applications="$HOME/Applications"
    nix_apps="$applications/Nix Apps"

    # Needs to be writable by the user so that home-manager can symlink into it
    if ! test -d "$applications"; then
        mkdir -p "$applications"
        chown ${username}: "$applications"
        chmod u+w "$applications"
    fi

    # Delete the directory to remove old links
    rm -rf "$nix_apps"
    mkdir -p "$nix_apps"
    find ${config.system.build.applications}/Applications -maxdepth 1 -type l -exec readlink '{}' + |
        while read src; do
            # Spotlight does not recognize symlinks, it will ignore directory we link to the applications folder.
            # It does understand MacOS aliases though, a unique filesystem feature. Sadly they cannot be created
            # from bash (as far as I know), so we use the oh-so-great Apple Script instead.
            /usr/bin/osascript -e "
                set fileToAlias to POSIX file \"$src\" 
                set applicationsFolder to POSIX file \"$nix_apps\"
                tell application \"Finder\"
                    make alias file to fileToAlias at applicationsFolder
                    # This renames the alias; 'mpv.app alias' -> 'mpv.app'
                    set name of result to \"$(rev <<< "$src" | cut -d'/' -f1 | rev)\"
                end tell
            " 1>/dev/null
        done
  '';

I have done something similar for home-manager, which integrates with this just fine.

Commit from my dotfiles: https://github.com/IvarWithoutBones/dotfiles/commit/0b3faad8bd1d0e1af6103caf59b206666ab742f4

hacker1024 commented 2 years ago

Folders symlinked to ~/Applications do not show up in spotlight, and copying them seems like a waste of disk space. Not to mention that it can take a while too if you have a lot of packages.

What about taking advantage of APFS's copy-on-write functionality to make a clone of the app bundle? That should avoid wasting resources, and it's as easy as cp -c.

The cloned bundles will have to be deleted and recreated before each update. This may cause issues with apps that store user data within their bundles, though, which is bad practice and uncommon.

cdmistman commented 1 year ago

@IvarWithoutBones's solution worked for applications installed with environment.systemPackages, but unfortunately the home-manager version of the script only works on previous home-manager generations' ~/Applications/Home Manager Apps.

I just spent most of my Sunday experimenting with the various already-posted solutions, if anybody wants to catch up on it you can see my comment here

jcszymansk commented 1 year ago

Hi,

I have encountered another issue: when the apps are linked, as now do both nix-darwin and home-manager, file associations don't get updated on switch. That is, when I right-click-open a file with an application, which is linked from the generation X, then switch, and then again right-click-open the same file with the same-name application, the instance from the generation X is picked up, not from the generation X+1. It changes only after manually opening the X+1-generation app.

vs49688 commented 1 year ago
 # Spotlight does not recognize symlinks, it will ignore directory we link to the applications folder.
            # It does understand MacOS aliases though, a unique filesystem feature. Sadly they cannot be created
            # from bash (as far as I know), so we use the oh-so-great Apple Script instead.

Bit late to the party, can confirm using APFS aliases works. You can avoid AppleScript with a tiny ObjC helper:

https://github.com/vs49688/mkalias/blob/master/mkalias.m

pshirshov commented 7 months ago

So, these two snippets work

  # see https://github.com/LnL7/nix-darwin/blob/master/modules/system/activation-scripts.nix
  system.activationScripts.postUserActivation.text = ''
    app_folder="$HOME/Applications/Nix Trampolines"
    rm -rf "$app_folder"
    mkdir -p "$app_folder"
    for app in $(find "${config.system.build.applications}/Applications" -type l); do
        app_target="$app_folder/$(basename $app)"
        real_app="$(readlink $app)"
        echo "mkalias \"$real_app\" \"$app_target\"" >&2
        ${pkgs.mkalias}/bin/mkalias "$real_app" "$app_target"
    done
  '';

home-manager:

  # don't forget to add 'com.apple.alias-file' without quotes into alfred's Extras
  home.activation = {
    aliasHomeManagerApplications = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
      app_folder="${config.home.homeDirectory}/Applications/Home Manager Trampolines"
      rm -rf "$app_folder"
      mkdir -p "$app_folder"
      for app in $(find "$genProfilePath/home-path/Applications" -type l); do
          app_target="$app_folder/$(basename $app)"
          real_app="$(readlink $app)"
          echo "mkalias \"$real_app\" \"$app_target\"" >&2
          $DRY_RUN_CMD ${pkgs.mkalias}/bin/mkalias "$real_app" "$app_target"
      done
    '';
  };

Although there are at least two issues:

  1. Permissions (e.g. Full Disk Access) do not survive package version updates because they are given directly to the apps in nix store
  2. Spotlight depresses the search results and Alfred needs additional configuration to even make the results visible.
pshirshov commented 7 months ago

There is a supposedly better version of my snippet: https://github.com/nix-community/home-manager/issues/1341#issuecomment-2049723843

pshirshov commented 7 months ago

Another approach (https://gist.github.com/berryp/7af4a1f534027807b26fff706a61b1ce):

  home.activation = {
    rsync-home-manager-applications = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
      rsyncArgs="--archive --checksum --chmod=-w --copy-unsafe-links --delete"
      apps_source="$genProfilePath/home-path/Applications"
      moniker="Home Manager Trampolines"
      app_target_base="${config.home.homeDirectory}/Applications"
      app_target="$app_target_base/$moniker"
      mkdir -p "$app_target"
      ${pkgs.rsync}/bin/rsync $rsyncArgs "$apps_source/" "$app_target"
    '';
  };
  system.activationScripts.postUserActivation.text = ''
    rsyncArgs="--archive --checksum --chmod=-w --copy-unsafe-links --delete"
    apps_source="${config.system.build.applications}/Applications"
    moniker="Nix Trampolines"
    app_target_base="$HOME/Applications"
    app_target="$app_target_base/$moniker"
    mkdir -p "$app_target"
    ${pkgs.rsync}/bin/rsync $rsyncArgs "$apps_source/" "$app_target"
  '';
remi-gelinas commented 5 months ago

Is there a reason it's suggested to setup trampolines to systems application bundles in the user's home directory, rather than copying/linking them to /Applications?

cdmistman commented 5 months ago

Is there a reason it's suggested to setup trampolines to systems application bundles in the user's home directory, rather than copying/linking them to /Applications?

trampolines are better than copying because they don't use the full storage of the application (as mentioned, this can be in the GBs), while they're better than linking because Spotlight doesn't index links in /Applications (see original issue description)

purcell commented 5 months ago

@cdmistman I think @remi-gelinas's question was "why /Users/myuser/Applications and not /Applications?" I don't think Spotlight behaviour is different between the two, but I'd personally expect that home-manager-controlled GUI apps would pop up under my home dir, while apps installed by nix-darwin would end up under /Applications. (I use @hraban's mac-app-util solution personally.)

mikhail5555 commented 4 days ago

Another approach (https://gist.github.com/berryp/7af4a1f534027807b26fff706a61b1ce):

  home.activation = {
    rsync-home-manager-applications = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
      rsyncArgs="--archive --checksum --chmod=-w --copy-unsafe-links --delete"
      apps_source="$genProfilePath/home-path/Applications"
      moniker="Home Manager Trampolines"
      app_target_base="${config.home.homeDirectory}/Applications"
      app_target="$app_target_base/$moniker"
      mkdir -p "$app_target"
      ${pkgs.rsync}/bin/rsync $rsyncArgs "$apps_source/" "$app_target"
    '';
  };
  system.activationScripts.postUserActivation.text = ''
    rsyncArgs="--archive --checksum --chmod=-w --copy-unsafe-links --delete"
    apps_source="${config.system.build.applications}/Applications"
    moniker="Nix Trampolines"
    app_target_base="$HOME/Applications"
    app_target="$app_target_base/$moniker"
    mkdir -p "$app_target"
    ${pkgs.rsync}/bin/rsync $rsyncArgs "$apps_source/" "$app_target"
  '';

After the latest 'linting' changes it seem the script needs to be changed to:

  system.activationScripts.postUserActivation.text = ''
    apps_source="${config.system.build.applications}/Applications"
    moniker="Nix Trampolines"
    app_target_base="$HOME/Applications"
    app_target="$app_target_base/$moniker"
    mkdir -p "$app_target"
    ${pkgs.rsync}/bin/rsync --archive --checksum --chmod=-w --copy-unsafe-links --delete "$apps_source/" "$app_target"
  '';

otherwise you get the error:

building the system configuration...
error: builder for '/nix/store/sa0mn78ngfggycd6lp0j60y4slln7jc7-darwin-system-24.05.20241107.83fb6c0+darwin5.5c74ab8.drv' failed with exit code 1;
       last 10 log lines:
       >
       > In /nix/store/ab8hv4x8dk7xl4h9j5l9azdx6yfschl1-darwin-system-24.05.20241107.83fb6c0+darwin5.5c74ab8/activate-user line 481:
       > /nix/store/q28y44w1zi6j98djla7cg2gy17fm9kf4-rsync-3.3.0/bin/rsync $rsyncArgs "$apps_source/" "$app_target"
       >                                                                   ^--------^ SC2086 (info): Double quote to prevent globbing and word splitting.
       >
       > Did you mean: 
       > /nix/store/q28y44w1zi6j98djla7cg2gy17fm9kf4-rsync-3.3.0/bin/rsync "$rsyncArgs" "$apps_source/" "$app_target"
       >
       > For more information:
       >   https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
       For full logs, run 'nix log /nix/store/sa0mn78ngfggycd6lp0j60y4slln7jc7-darwin-system-24.05.20241107.83fb6c0+darwin5.5c74ab8.drv'.