iqan 0.3.4

Sync Nix flake pins
# íqán

Helps you sync Nix flake pins, so you don't end up carrying fifty
ever-so-slightly different Nixpkgs in your store.

Has three modes of operation.


## plan mode

`iqan plan.json`

You give íqán a JSON file which looks like this:

```json
{
  "source": "/Users/kivikakk/g/vyx",
  "targets": {
    "/Users/kivikakk/g/a1d": ["nixpkgs", "fenix"],
    "/Users/kivikakk/g/chog": {"nixpkgs-erlang": "nixpkgs"},
    "/Users/kivikakk/g/cmark-gfm-hs": ["nixpkgs"],
    "/Users/kivikakk/g/comrak": ["nixpkgs", "fenix"],
    "/Users/kivikakk/g/iqan": ["nixpkgs", "fenix"],
    "/Users/kivikakk/g/kivikakk": ["nixpkgs"],
    "/Users/kivikakk/g/koino": ["nixpkgs"],
    "/Users/kivikakk/g/kv": {"nixpkgs-erlang": "nixpkgs", "fenix": true},
    "/Users/kivikakk/g/nossa": {"nixpkgs-erlang": "nixpkgs", "fenix": true},
    "/Users/kivikakk/g/notes": ["nixpkgs"],
    "/Users/kivikakk/g/tahetriiv": ["nixpkgs", "fenix"]
  }
}
```

íqán proceeds through each target, and compares the named inputs to those in the
source.  The inputs can be a list, which means inputs have the same name in both
source and target, or a map of input names in source to target (or `true`, as a
shorthand for the same).

"Original mismatches" --- where the input specifications are different, not just
the locked version[^jfc] --- are detected, and can be resolved in `flake.nix` as
well as your lock file.

[^jfc]: I got a jumpscare reading this back in September 2026, because it reads
    like pure slop despite [predating] the "it's X, not Y" torrent by a good six
    months at least. I badly want to remove it just because of how much it icks
    me out now, but, in accordance with my [values], I will hold out, for now.
    Certainly don't find myself ever wanting to write that kind of thing today,
    tho!

[predating]: https://nossa.ee/~talya/iqan/commit/main/5d65c9d75bed38126f36422cc25e00e73c02fcdc?k=Syp1yfWAEdQ6UfS9N6My_f7HmDGXsFdQBWzY2kT1jk8%3D#README.md-R33
[values]: https://kivikakk.ee/2026/05/23/on-llms-v#punctuation

íqán prompts you before making any change to anything, and only modifies
`flake.lock` files specified in your `plan.json`'s `targets` section, and
`flake.nix` files likewise located when an original mismatch occurs.

`flake.lock` changes are made by parsing and writing out the JSON. íqán tries
not to make any formatting changes vis-à-vis `nix flake lock`; if it does, send
me a bug report :)

`flake.nix` changes are made by parsing with
[rnix](https://github.com/nix-community/rnix-parser), locating the syntax node
corresponding to the input being changed, and then replacing just that text
span in the source.  The changes are made conservatively, matching the expected
existing value (as calculated from `flake.lock`), and if íqán cannot be sure of
what it's doing, it aborts and lets you handle it.


## one-shot mode

`iqan path/to/src/`

You run íqán in the target flake's directory, and give the directory of the
source flake.  It'll run on all inputs in the target, prompting you as above
where the source has a matching input.


## tarball mode

`iqan tarball`

You run íqán in a flake's directory. It inspects your `flake.nix`/`flake.lock`'s
`github:NixOS/nixpkgs` inputs, detects which can be switched to
nixos.org tarballs per
[PSA: Use nixos.org tarballs for your flake inputs!](https://discourse.nixos.org/t/psa-use-nixos-org-tarballs-for-your-flake-inputs/79950),
and prompts you for each if you'd like to switch.


## install

`cargo install iqan` will do, or `cargo build --release` from source.
The Nix flake will build it for you, if you like.


## license

Copyright © 2025–2026 Asherah Connor \<ashe@kivikakk.ee\>

This work is free. You can redistribute it and/or modify it under the terms of
the Do What The Fuck You Want To Public License, Version 2, as published by Sam
Hocevar. See the [COPYING](COPYING) file for more details.