This is a simple nix library to help generate development environment CLIs for projects.
I often find myself wanting to create development environment scripts for common
things like testing, linting, auto-fixing code, etc. Further, these tasks are
composed of sub-tasks that are determined by the languages I’m working with,
tooling nuances for the project, etc. However, in general, I pretty much always
want the ability to group those commands in logical ways and parallelize the
runs of those commands (in addition to running those commands manually) – for
instance, I want to be able to run some singular test
command and spawn off
processes for each language-specific testing utility.
This library provides a simple nix utility for generating a such a cli script.
Consider the following flake.nix
:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
mkCli.url = "github:cprussin/mkCli";
};
outputs = {
nixpkgs,
flake-utils,
mkCli,
...
}: (
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = import nixpkgs {
inherit system;
overlays = [mkCli.overlays.default];
config = {};
};
cli = pkgs.lib.mkCli "cli" {
_noAll = true;
test = {
lint = {
nix = "${pkgs.statix}/bin/statix check .";
js = "${pkgs.nodejs}/bin/npm exec eslint **/**";
};
dead-code.nix = "${pkgs.deadnix}/bin/deadnix .";
format = {
nix = "${pkgs.alejandra}/bin/alejandra --check .";
js = "${pkgs.nodejs}/bin/npm exec prettier --check .";
};
};
fix = {
lint = {
nix = "${pkgs.statix}/bin/statix fix .";
js = "${pkgs.nodejs}/bin/npm exec eslint --fix";
};
dead-code.nix = "${pkgs.deadnix}/bin/deadnix -e .";
format = {
nix = "${pkgs.alejandra}/bin/alejandra .";
js = "${pkgs.nodejs}/bin/npm exec prettier --write .";
};
};
};
in {
devShells.default = pkgs.mkShell {
buildInputs = [
pkgs.git
pkgs.nodejs
cli
];
};
}
)
);
}
Then, inside your nix shell you’ll be able to run the following:
> cli -h # Get a help string for the entire CLI
> cli test -h # Get a help string for just the test sub-tree of the CLI
> cli test # Run all test commands in parallel (with a prefix prepended to output)
> cli test lint nix # Only run the `statix check .` command
Use the default overlay in the flake, which will inject mkCli
onto pkgs.lib
:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
mkCli.url = "github:cprussin/mkCli";
};
outputs = {
nixpkgs,
flake-utils,
mkCli,
...
}: (
flake-utils.lib.eachDefaultSystem
(
system: let
pkgs = import nixpkgs {
inherit system;
overlays = [mkCli.overlays.default];
config = {};
};
cli = pkgs.lib.mkCli "cli" { ... };
in {
devShells.default = pkgs.mkShell {
buildInputs = [ cli ];
};
}
)
);
}
Pretty simple, just pass mkCli
two arguments: the first is a string which
specifies the name of the CLI script, and the second is an attrset of either
attrsets or strings. The second argument should be a tree that represents what
the CLI should do. String values indicate leaf nodes, attrset values indicate
sub-commands. If you do not specify _noAll = true;
on a particular node, then
an all
command will be generated which will run all descendant leaf nodes in
parallel (this will also become the default command if no argument is passed,
instead of showing help for that node).