Local/personal development tools with flakes?

I have a few projects for which I want to commit a flake.nix file to the repository for development purposes. This would be a basic flake that sets up various dependencies needed to run/develop the project.

However, is there a way to “extend” a flake in the repository with my personal/local development tools?
For example, I am using IntelliJ, so I need to set up some paths for it, but other colleagues might use a language-server-based editor.
I don’t want the flake to have to contain all setup/code for possible editors/workflows.

The question is thus: I have a repository with a flake.nix file. How would I “add” my personal development tools to this file, without committing them?
Is there a way to inject certain modules from my global NixOS file (probably not)? Should I add another local.nix file and somehow load it as well? Should I just give up and include setup for multiple dev flows, even if I don’t use them?

7 Likes

You can have direnv load the devShells for multiple flakes in one environment. I just tested it myself.

In your .envrc:

use flake .
use flake ~/some_personal_flake_dir
3 Likes

Hmm, that’s interesting. However, as I currently don’t use direnv, I was looking for a “pure” nix solution.

Looking at the code for direnv, I suppose one could do something similar with just commands, or even nix develop #flake-a and then nix develop #flake-b, but it isn’t very handy.

Perhaps it is time for me to use direnv.

Well the solution of nested nix-shell/nix develop is quite clever I guess as it has the advantage of working even when the parent flake has not created any hook for you to modify the environment.

If it’s too long to type you can certainly write a script that runs nix-shell a.nix --command "nix-shell b.nix".

Otherwise you can maybe modify the flake to check if a file exists using builtins.pathExists and load your dev code that way, but if you use git this file must be added to git locally or flake will ignore it. Not sure if there an easy solution for that without changing git commit hooks…

can you not just have your flake-b depend on flake-a as an input?

3 Likes

To add to what @uep suggested.
You can use path: for flake inputs url.
I have a multi flake repo with a flake on the root folder and one inside a folder called bin.
My main flake looks like this:

[...]
input = {
   scripts.url = "path:./bin";
};
[...]

Just be aware that this will update your flake.lock file to include the new input, so you will need to revert the change after running if you don’t want to commit it to your repo.

I guess with this approach you would need to merge the two flake outputs. So how would you merge two flakes (or load all outputs of a flake into another)?

There’s a way you can do this without disrupting your main flake.lock. It also doesn’t require running nix develop multiple times.

  1. Create subdirectory in your project. Say mkdir extra.
  2. Create a new extra/flake.nix file. Have that flake refer to the main flake.nix as an input.
  3. Add extra/flake.nix and extra/flake.lock to the git index but hide it from your commits.
git add --intent-to-add extra/flake.nix
git update-index --assume-unchanged extra/flake.nix

Here’s what your extra/flake.nix might look like (you could write a cleaner flake, but I hope you get the idea):

{
  description = "Extra";
  inputs.otherFlake.url = "path:..";
  outputs = { self, otherFlake, ... }:
    {
      devShells.x86_64-linux = let
        pkgs = import otherFlake.inputs.nixpkgs { system = "x86_64-linux"; };
      in {
        default = pkgs.mkShell {
          buildInputs =
            otherFlake.outputs.devShells.x86_64-linux.default.buildInputs
            ++ [ pkgs.hello ];
        };
      };
    };
}

Then you can just run nix develop ./extra instead of nix develop . (no direnv required).

4 Likes