How can I access `config` attributes inside of a flake's `outputs`?

In a given module that I’m importing in a flake-based home-manager conf, I am referencing the config.home.homeDirectory attribute. I would like to define an attribute accessible by my flake’s outputs (i.e. in a preceding let statement) which is homeDir = config.home.homeDirectory. However, of course, the config attribute set is not immediately available to me in flake.nix like it is in an imported module (as far as I can tell).

Is there a method by which i can access config’s as I’d like to?

You can always open up a nix repl, and do a = builtins.getFlake (toString ./.) this assumes you’re in the directory with your flake, and you can use tab complete to view into what a (your flake) evaluates to.

2 Likes

Ah Mr. Ringer, thank you! This is certainly a useful trick, and very good to know, but I don’t know if it bodes well for my use-case here. Now that I have access to the code I’m trying to write, let me elaborate, and provide the Y to my X-Y Problem.

So, among others, I have a neovim config that I would like to be able to play/experiment with–without the need to constantly rebuild/reactivate my flake every change.

My directory layout is as follows:

flake.nix
modules/
  home/
    nvim/
     default.nix
     lua/
       me/init.lua

The current strategy is to use the following in modules/home/nvim/default.nix to symlink the neovim config in the store to an out-of-store file:

{ pkgs, config, lib, ... }:

#...

xdg.configFile."nvim/lua/me/init.lua".source = 
  config.lib.file.mkOutOfStoreSymlink(config.home.homeDirectory 
    + "/path/to/flake/modules/home/nvim/lua/me/init.lua")

However now, I’ve seen explained before that doing this does defeat the purpose of flakes a little bit, making the config ultimately less declarative/robust, which makes sense. So, to remedy this (and also as a bit of an experiment to see if I can do it or not), I am trying to create something like the following in my flake.nix:

#...

outputs = inputs@{ self, nixpkgs, home-manager, ... }:
let
repoDirName = "nix-home-redux";
homeRepoDirPath = "workbench/${repoDirName}"
linkConfig = rec {
  liveConfig = true;
  flakeRoot = self.outPath;
  externalHomeRoot = "${config.home.homeDirectory}/${homeRepoDirPath}";
  to = path: (
    if liveConfig 
    then (config.lib.file.mkOutOfStoreSymlink "${externalHomeRoot}/${path}")
    else "${flakeRoot}/${path}");
};
in
{
#...
  homeManagerConfigurations.linux-server = home-manager.lib.homeManagerConfiguration rec {
    system = "x86_64-linux";
    username = "me";
    homeDirectory = "/home/${username}";
    extraSpecialArgs = { inherit inputs; };
    stateVersion = "21.05";
    configuration = { imports = [ ./modules/home/nvim ]; };
  };
#... 
}

Where I would then ideally be able to provide linkConfig to ./modules/home/nvim and be able to now rewrite the earlier xdg.config setting as:

xdg.configFile."nvim/lua/me/init.lua".source = linkConfig.to "modules/home/nvim/lua/me/init.lua";

As you can tell, I’m still a few steps away from a final solution here.

My current hold-up is that I can’t actually reference config at all in the let bindings, is there anything that would allow me to get my hands on something like that there?

I’m not sure it’s the cleanest way of handling things, but you could turn linkConfig into a function taking the config and pass it to Home Manager via extraSpecialArgs. The following is untested, but it ought to work.

#...

outputs = inputs@{ self, nixpkgs, home-manager, ... }:
let
repoDirName = "nix-home-redux";
homeRepoDirPath = "workbench/${repoDirName}"
linkConfig = config: rec {
  liveConfig = true;
  flakeRoot = self.outPath;
  externalHomeRoot = "${config.home.homeDirectory}/${homeRepoDirPath}";
  to = path: (
    if liveConfig 
    then (config.lib.file.mkOutOfStoreSymlink "${externalHomeRoot}/${path}")
    else "${flakeRoot}/${path}");
};
in
{
#...
  homeManagerConfigurations.linux-server = home-manager.lib.homeManagerConfiguration rec {
    system = "x86_64-linux";
    username = "me";
    homeDirectory = "/home/${username}";
    extraSpecialArgs = { inherit inputs linkConfig; };
    stateVersion = "21.05";
    configuration = { imports = [ ./modules/home/nvim ]; };
  };
#... 
}
{ pkgs, config, lib, linkConfig, ... }:

#...

xdg.configFile."nvim/lua/me/init.lua".source = (linkConfig config).to "modules/home/nvim/lua/me/init.lua";
1 Like

EDIT THE MODULES ARE BROKEN RIGHT NOW ONLY HOME MANAGER WORKS I DID IT ON PURPOSE THIS BRANCH IS STILL A WORK IN PROGRESS BUT ITS COOL

https://github.com/BirdeeHub/nixCats-nvim/tree/nixCats-5.0.0

In particular, the

nix flake init -t github:BirdeeHub/nixCats-nvim/nixCats-5.0.0#nixExpressionFlakeOutputs

template does what you want.

See it in action here

it is exported through common/default.nix to the outputs of the system flake.

Ok well the modules work again but the templates are outdated now.