Direct store references not working in xmonad.hs file

I have been converting my system configuration to flakes, including home-manager configuration through its module. I am at the point of using home.file to manage various dotfiles, etc. I ran across a situation that I can’t explain: in my xmonad.hs file, my source file’s main function looks like:

main = do h <- spawnPipe $ "@xmobar@ ~/.xmonad/xmobarrc"
          xmonad $ docks $ defaults { logHook = myLogHook h }

and my home.nix module has this to configure xmonad.hs (thanks rmcgibbo!):

  home.file = with nixpkgs; {
    ".xmonad/xmonad.hs".source = nixpkgs.substituteAll {
      src = ./sources/xmonad.hs;


      xmobar = "${xmobar}/bin/xmobar";

resulting in a ~/.xmonad/xmonad.hs file that includes:

main = do h <- spawnPipe $ "/nix/store/mnyiiq9y8vg851z1j8v49fq1z75cr5mj-xmobar-0.43/bin/xmobar ~/.xmonad/xmobarrc"
          xmonad $ docks $ defaults { logHook = myLogHook h }

Looks great! However, this configuration does not work–when I log in, xmobar does not run (leaving the bar area blank). If I also include xmobar in the environment.systemPackages portion of my system configuration, then it does work.

This doesn’t seem to be a problem in other runtimes. For instance, I got the very idea of not including packages like xmobar in my system packages list from enabling nm-applet via home-manager–that setup seems to use a similar approach of keeping the nm-applet binary out of the user path, but nonetheless invoking it directly through a store path when needed. And for a specific shell script that my xmobar setup uses (to capture information of battery level and charging state) is able to run acpi with a direct store reference without being installed in systemPacakges. So perhaps this is something about how Haskell work, or XMonad.Util.Run.spawn.

If anyone has an explanation for this, I’d really appreciate it. This is less about making it work on my system, and more about patching up my mental model of what’s going on. In the end, I’d like to do the “pure” thing and remove xmobar and other packages (alacritty for launching terminals; rofi for showing an app launcher; etc.) from my package list.


I figured out what’s going on. This has to do with how XMonad works, specifically its behavior in recompiling under the XMonad restart function.

I think because the ~/.xmonad/xmonad.hs symlink into the nix store that the home-manager module installs looks to XMonad like a file that has not changed (due to the zero timestamp all files in the store carry). And so when I was restarting XMonad, expecting the changes in the config to be applied, I was just getting my original config back, which refers to external programs by their binary name, as though they’re on the path – which is exactly why I need to install these packages through in my profile in order for XMonad to work.

I changed the restart line from restart "xmonad" True to something like this line in @gvolpe’s setup. This works beautifully (though I have questions about whether this is a good way to force a recompilation).