Cache the nix package list, query and sort by relevance.
Find installable packages at lightning speed and sort the result by relevance, split by ...
- indirect hits - packages that contain the search string,
- direct hits - packages that start with the search string,
- exact hits - the package that matches your exact search string,
... in configurable individual colors, optionally separated by a newline. Have a look:
nix run github:OleMussmann/nps -- COMMAND_LINE_OPTIONS
nix --extra-experimental-features "nix-command flakes" run github:OleMussmann/nps -- COMMAND_LINE_OPTIONS
⚠️ The way of installing third-party flakes is highly dependent on your personal configuration. As far as I know there is no standardized, canonical way to do this. Instead, here is a generic approach via overlays. You will need to adapt it to your config files.
Add nps
to your inputs:
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
# Nix Package Search - nps
nps.url = "github:OleMussmann/nps";
nps.inputs.nixpkgs.follows = "nixpkgs";
};
Add an overlay to your outputs:
outputs = { self, nixpkgs, ... }@inputs:
let
third-party-packages = final: prev: {
nps = inputs.nps.packages.${prev.system}.default;
<other third party flakes you have>
};
in {
nixosConfigurations."<hostname>" = nixpkgs.lib.nixosSystem {
system = "<your_system_architecture>";
modules = [
({ config, pkgs, ... }: { nixpkgs.overlays = [ third-party-packages ]; })
./configuration.nix
];
};
};
Finally, add nps
to your systemPackages
in configuration.nix
:
environment.systemPackages = with pkgs; [
other_packages
third-party-packages.nps
...
];
Add nps
to your systemPackages
in configuration.nix
:
environment.systemPackages = with pkgs; [
other_packages
# Nix Package Search - nps:
(builtins.getFlake "github:OleMussmann/nps").packages.${builtins.currentSystem}.nps
...
];
- Clone this repository and
cd nps
into it. - Build with
cargo build --release
. Dependencies needed:gcc
,cargo
- Copy or symlink the
target/release/nps
executable to a folder in yourPATH
, or include it in yourPATH
.
Instead of running nps -r
(or nps -e -r
for using the nix "experimental" features a.k.a flakes) by hand every once in a while to refresh the package cache, or you can set up a systemd timer at regular intervals. If you automate it, make sure to do so with your local user environment.
systemd.timers."refresh-nps-cache" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "weekly"; # or however often you'd like
Persistent = true;
Unit = "refresh-nps-cache.service";
};
};
systemd.services."refresh-nps-cache" = {
# Make sure `nix` and `nix-env` are findable by systemd.services.
path = ["/run/current-system/sw/"];
serviceConfig = {
Type = "oneshot";
User = "REPLACE_ME"; # ⚠️ replace with your "username" or "${user}", if it's defined
};
script = ''
set -eu
echo "Start refreshing nps cache..."
# ⚠️ note the use of overlay (as described above), adjust if needed
# ⚠️ use `nps -dddd -e -r` if you use flakes
${pkgs.third-party-packages.nps}/bin/nps -r -dddd
echo "... finished nps cache with exit code $?."
'';
};
-
Test the service by starting it by hand and checking the logs.
sudo systemctl start refresh-nps-cache.service journalctl -xeu refresh-nps-cache.service
-
Test your timer by letting it run, for example, every 5 minutes. Adjust the timers as follows.
-OnCalendar = "weekly"; +OnBootSec = "5m"; +OnUnitActiveSec = "5m";
Check the logs if it ran successfully.
journalctl -xeu refresh-nps-cache.service
⚠️ Don't forget to revert your changes afterwards.
nps PACKAGE_NAME
searches the cache file for packages matching thePACKAGE_NAME
search string.- The cache is created on the first call. Be patient, it might take a while. This is done under the hood by capturing the output of
nix-env -qaP
(ornix search nixpkgs ^
for "experimental"/flake mode). Subsequent queries are much faster.
Find SEARCH_TERM in available nix packages and sort results by relevance.
List up to three columns, the latter two being optional:
PACKAGE_NAME <PACKAGE_VERSION> <PACKAGE_DESCRIPTION>
Matches are sorted by type. Show 'indirect' matches first, then 'direct' matches, and finally 'exact' matches.
indirect fooSEARCH_TERMbar (SEARCH_TERM appears in any column)
direct SEARCH_TERMbar (PACKAGE_NAME starts with SEARCH_TERM)
exact SEARCH_TERM (PACKAGE_NAME is exactly SEARCH_TERM)
Usage: nps [OPTIONS] [SEARCH_TERM]
Arguments:
[SEARCH_TERM]
Search for any SEARCH_TERM in package names, description or versions
Options:
-c, --color[=<COLOR>]
Highlight search matches in color
[env: NIX_PACKAGE_SEARCH_COLOR_MODE=]
[default: auto]
[aliases: colour]
[possible values: auto, always, never]
-C, --columns[=<COLUMNS>]
Choose columns to show
[env: NIX_PACKAGE_SEARCH_COLUMNS=]
[default: all]
Possible values:
- all: Show all columns
- none: Show only PACKAGE_NAME
- version: Also show PACKAGE_VERSION
- description: Also show PACKAGE_DESCRIPTION
-d, --debug...
Turn debugging information on
Use up to four times for increased verbosity
-e, --experimental[=<EXPERIMENTAL>]
Use experimental flakes
[env: NIX_PACKAGE_SEARCH_EXPERIMENTAL=]
[default: false]
[possible values: true, false]
-f, --flip[=<FLIP>]
Flip the order of matches and sorting
[env: NIX_PACKAGE_SEARCH_FLIP=]
[default: false]
[possible values: true, false]
-i, --ignore-case[=<IGNORE_CASE>]
Ignore case
[env: NIX_PACKAGE_SEARCH_IGNORE_CASE=]
[default: true]
[possible values: true, false]
-q, --quiet[=<QUIET>]
Suppress non-debug messages
[env: NIX_PACKAGE_SEARCH_QUIET=]
[default: false]
[possible values: true, false]
-r, --refresh
Refresh package cache and exit
-s, --separate[=<SEPARATE>]
Separate match types with a newline
[env: NIX_PACKAGE_SEARCH_PRINT_SEPARATOR=]
[default: true]
[possible values: true, false]
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Apart from command line flags, nps
can be configured with environment variables. You can set these in your config file. Below are the defaults. Uncomment and change the ones you need.
environment.sessionVariables = {
#NIX_PACKAGE_SEARCH_EXPERIMENTAL = "false"; # Set to "true" for flakes
#NIX_PACKAGE_SEARCH_FLIP = "false";
#NIX_PACKAGE_SEARCH_CACHE_FOLDER_ABSOLUTE_PATH = "/home/YOUR_USERNAME/.nix-package-search";
#NIX_PACKAGE_SEARCH_COLUMNS = "all";
#NIX_PACKAGE_SEARCH_EXACT_COLOR = "magenta";
#NIX_PACKAGE_SEARCH_DIRECT_COLOR = "blue";
#NIX_PACKAGE_SEARCH_INDIRECT_COLOR = "green";
#NIX_PACKAGE_SEARCH_COLOR_MODE = "auto";
#NIX_PACKAGE_SEARCH_PRINT_SEPARATOR = "true";
#NIX_PACKAGE_SEARCH_IGNORE_CASE = "true";
};
Use the experimental nix search
command. It pulls information from the nix flake registries instead of nix channels. This is useful if no channels are in use, or channels are not updated regularly.
- default: false
- possible values: true, false
Flip the order of matches? By default most relevant matches appear below, which is easier to read with long output. Flipping shows most relevant matches on top.
- default: false
- possible values: true, false
Absolute path of the cache folder
- default: /home/YOUR_USERNAME/.nix-package-search
- possible values: path
Choose columns to show: PACKAGE_NAME plus any of PACKAGE_VERSION or PACKAGE_DESCRIPTION
- default: all
- possible values: all, none, version, description
Color of EXACT matches, match SEARCH_TERM in PACKAGE_NAME
- default: magenta
- possible values: black, blue, green, red, cyan, magenta, yellow, white
Color of DIRECT matches, match SEARCH_TERMbar in PACKAGE_NAME
- default: blue
- possible values: black, blue, green, red, cyan, magenta, yellow, white
Color of INDIRECT matches, match fooSEARCH_TERMbar in any column
- default: green
- possible values: black, blue, green, red, cyan, magenta, yellow, white
Show search matches in color
- default: auto (only show color if stdout is in terminal, suppress if e.g. piped)
- possible values: always, never, auto
Separate matches with a newline?
- default: true
- possible values: true, false
Suppress non-debug messages?
- default: false
- possible values: true, false
Search ignore capitalization for the search?
- default: true
- possible values: true, false
- Check existing issues or open a new one to suggest a feature or report a bug.
- Fork the repository, check the DEVELOPMENT.md and make your changes
- Open a pull request