kivikakk.ee

I use Nix flakes a lot — both in development, and in how I deploy artefacts. (You can see my primary flake’s 17 inputs!)

One thing that has gotten a bit annoying, though, has been keeping the pins somewhat in sync. I regularly end up with a dozen nixpkgs and fenix and (etc. etc. etc.) variants in my Nix store, meaning I’d also have half a dozen different Rust, Erlang, Elixir and whatever other versions installed too. If I dare nix-collect-garbage -d, then working on any given project might give me a surprise as it turns out it had a slightly older pin and I actually need to wait for its special magical Elixir version.

And so on!

Using inputs.X.follows is all good and well when combining them into a unified whole, but I don’t use (and don’t intend to use) global devShells — I want each project to stand on its own. So, instead, I want a way to compare and optionally sync the locked versions from some reference to my projects. For a while I found it was a good enough hack to just cp ~/g/vyx/flake.lock . and then let the next Nix invocation remove all the irrelevant ones … but then I’d introduce a dependency which hitched its own nixpkgs along for the ride, and for Reasons™ that would get called "nixpkgs" in flake.lock, and my actual primary Nixpkgs pin called "nixpkgs_2". For a while I was then accidentally using that reference everywhere. Goodness.

Here’s íqán. It takes a plan file, which specifies the source (Vyx, for me), and then a list of targets along with which inputs should be synced. Here’s an excerpt of a sample run:

$ iqan ./iqan.json
Source: /Users/kivikakk/g/vyx
Target: /Users/kivikakk/g/a1d
-----------------------------
input nixpkgs is synced
input fenix is synced
Target: /Users/kivikakk/g/chog
------------------------------
input nixpkgs is synced
Target: /Users/kivikakk/g/cmark-gfm-hs
--------------------------------------
input nixpkgs is synced
Target: /Users/kivikakk/g/comenzar
----------------------------------
input nixpkgs is ahead of source (!)
source: 1751741127 (2025-07-05 18:45:27 UTC)
target: 1752620740 (2025-07-15 23:05:40 UTC)
(S)ync to source, or (I)gnore? s
Target: /Users/kivikakk/g/comrak
--------------------------------
input nixpkgs is behind source
source: 1751741127 (2025-07-05 18:45:27 UTC)
target: 1748437600 (2025-05-28 13:06:40 UTC)
(S)ync to source, or (I)gnore? s
input "fenix" has an original mismatch
source: github:nix-community/fenix
target: github:nix-community/fenix/monthly
(S)ync to source, or (I)gnore? s
[!!!] update flake.nix please!
Target: /Users/kivikakk/g/iqan
------------------------------
input nixpkgs is synced
input fenix is synced
Target: /Users/kivikakk/g/kivikakk
----------------------------------
input nixpkgs is synced
Target: /Users/kivikakk/g/koino
-------------------------------
input nixpkgs is synced
Target: /Users/kivikakk/g/kv
----------------------------
input nixpkgs is synced
input fenix is synced
Target: /Users/kivikakk/g/nossa
-------------------------------
input nixpkgs is synced
input fenix is synced
Target: /Users/kivikakk/g/notes
-------------------------------
input nixpkgs is synced
Target: /Users/kivikakk/g/outfoxsync
------------------------------------
input "nixpkgs" has an original mismatch
source: github:NixOS/nixpkgs/nixos-25.05
target: github:NixOS/nixpkgs/nixos-24.11
(S)ync to source, or (I)gnore? s
[!!!] update flake.nix please!
$

It does the job. :)