The code below lets you create a directory in your home-manager config that auto-creates symlinks for non-Nix dotfiles from ~/.config/ using xdg.configFile and mkOutOfStoreSymlink. This gives the following advantages:
- You can keep all your non-Nix dotfiles in your home-manager repo.
- You don't have to do
home-manager switchon each dotfile change. Changes are instantly reflected. - You don't need to hard-code the paths for each symlink, the linking is instead file-based. Just add the new dotfile to the directory, and you're done.
For example, if your home-manager config is in ~/nixos/ and looks like this...:
~/nixos
├── ...
├── flake.nix
└── configs
├── starship.toml
└── fish
└── config.fish
...then home-mamager will create the following symlinks in ~/.config:
~/.config
├── ...
├── starship.toml -> ~/nixos/configs/starship.toml
└── fish
└── config.fish -> ~/nixos/configs/fish/config.fish
Don't forget to git add when adding a new dotfile. Otherwise, they will be ignored by Nix. Then run home-manager switch to create the new symlink.
{ config }:
let
# -------------------------------------------------------------------------
# `configsPath`: a path value to a directory who's files/directories
# should be symlinked to from `~/.config/`.
#
# `configsAbsolutePath`: an absolute path to `configsPath`.
#
# The reason this function requires two path parameters to the same
# directory is that it uses `builtins.readDir` which would require
# `--impure` if only an absolute path were used. If using only a literal
# Nix path, the symlinks would point to the Nix store, and thereby require
# a build whenever a config file is edited.
#
# `returns`: an attribute set suitable for `xdg.configFile`.
# -----------------------------------------------------------------
configSymlinks = configsPath: configsAbsolutePath:
let
inherit (config.lib.file) mkOutOfStoreSymlink;
mkSymlink = name: {
name = name;
value.source = mkOutOfStoreSymlink "${configsAbsolutePath}/${name}";
};
in configsPath
|> builtins.readDir
|> builtins.attrNames
|> map mkSymlink
|> builtins.listToAttrs;
in {
# Change the arguments to point to your `configs` directory
xdg.configFile = configSymlinks ./configs "~/nixos/configs";
}Please let me know if there's some way to improve the implementation so that you only have to pass in one path parameter.
It works similary to stow when the
removePrefixDirectoryis set totrue, so does files likenvim/.config/nvim/init.luaare symlinked to~/.config/nvim/init.lua. Other files that lives in~/.configare not tracked if not in the repo.Neovim sometimes add other files in the
~/.config/nvimfolder that I don't mind tracking as most of my config lives in eitherinit.luaorluafolder. You could also just symlinknvimfolder directly and track everything.