Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
spease opened this issue Aug 6, 2020 · 22 comments

Comments

@spease
Copy link

spease commented Aug 6, 2020

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
Copy link

jsravn commented Aug 25, 2020

@spease It's currently bugged in nix-darwin. There is a workaround at #139 (comment). Hopefully it will get a fix soon - it should be easy to make a PR for it.

@purcell
Copy link
Contributor

purcell commented Aug 25, 2020

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
Copy link
Author

spease commented Aug 25, 2020

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
Copy link
Owner

LnL7 commented Aug 26, 2020

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

@wangkev
Copy link

wangkev commented Aug 28, 2020

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.

@what-the-functor
Copy link

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
Copy link

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
Copy link

leira commented Jan 20, 2022

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
Copy link

IvarWithoutBones commented Aug 29, 2022

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: IvarWithoutBones/dotfiles@0b3faad

@hacker1024
Copy link

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
Copy link

@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
Copy link

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
Copy link

vs49688 commented Nov 15, 2023

 # 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
Copy link
Contributor

pshirshov commented Apr 10, 2024

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
Copy link
Contributor

There is a supposedly better version of my snippet: nix-community/home-manager#1341 (comment)

@pshirshov
Copy link
Contributor

pshirshov commented Apr 11, 2024

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
Copy link

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
Copy link

cdmistman commented May 29, 2024

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
Copy link
Contributor

purcell commented May 29, 2024

@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
Copy link

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'.

@jpsecher
Copy link

jpsecher commented Dec 7, 2024

For Home Manager, I had to do this:

 system.activationScripts.postUserActivation.text = ''
   apps_source="$HOME/Applications/Home Manager Apps"
   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"
 '';

@pshirshov
Copy link
Contributor

Almost all the approaches, including trampolines, are affected by this: hraban/mac-app-util#19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests