Calling external commands from nur

If you want to execute any external command you can do that by just calling those commands as you are used to. If you for example want to run poetry install when using nur install you can do that like this:

def "nur install" [] {
    poetry install
}

Provide nur tasks for wrapping shell commands

If you want to use a nur to run and wrap any normal command - for example to ensure you can run this in any subdirectory of your project - I recommend using the following schema (using the poetry package manager as an example):

def --wrapped "nur poetry" [...args] {
    poetry ...$args
}

The important bit is using --wrapped, so the nu parser will not try to match flags starting with - into your nur task.

See the docs for def for some more details.

Avoid external command naming conflicts

If you want to run external commands you might run into the issue that nu itself provides some builtin commands that might match the name of the command you want to run. This for example is the case for sort, where nu has it’s own version (see sort command). Most of the time it makes sense to use the versions nu provides as those implement all the pipeline improvements of nu. If you want to call the external command and not the builton function by nu use ^sort instead of sort in your nur tasks.

The same rule applies to your user defined functions, you would for example provide a function named grep (def grep [] { ... }) which could call the grep command using ^grep.

Example calling ls and sort system commands:

def "nur call-sort" [] {
    ^ls | ^sort
}

My recommendation would be to embrace the nu builtin commands and use the structured data those provide and consume as much as possible. See “Some notes about pipelines and how nu handles those” below for some more details on this.

About pipelines and how nu handles those

The way nu shell handles pipelines is a bit different from normal UNIX shells. For me this is part of the nu superpowers and the reason I think nu is the perfect choice for building a task runner.

Normal UNIX shells always use text to pass data from stdout (or stderr) to the next command via stdin. This is pretty easy to implement and a very slim contract to follow. nu however works quite different from this. Instead of passing text when using pipelines, it tries to use structured data. Think of this like, passing JSON between the different commands. This increases the flexibility and structured way to work with the data in a great way.

For example getting the ID of a running container in docker would look somewhat like this in a normal UNIX shell:

docker ps | grep some-name | head -n 1 | awk '{print $1}'

This works for most of the cases, but might produce errors for example of a container named this-also-contains-some-name-in-its-name exists. This issue exists as we are parsing text data, not some actual structured data. So having the name anywhere in a line will result in that line being used. (Note: I know about docker ps --filter ..., this is just to explain the overall issue of parsing text data)

nu works on structured data and provides commands to filter, sort or restructure that data in any way you like. Also nu provides mechanics to import text data into this structured format. Getting the docker ps text data input nu can for example be done using docker ps | from ssv (“ssv” stands for “space-separated values”), see the command from for more possible input formats.

To get the first container matching using the image some-name you could use this command:

docker ps | from ssv | where IMAGE == "some-name" | get "CONTAINER ID" | first

This is using the where command to match only a single row and then the get command to reduce the row to just one column. There are also many more commands to work with structured data.

This way of working with command data in a very structured form is very much superior to how normal shells used to work. This is especially good when you are creating more complex scripts and thus also true for the tasks you will write in your task runner. This is why I did choose nu for creating nur.

I recommend reading thinking in nu to get a grasp about this concept and start using nu script in nur in a very structured way. Also you may want to read the nu documentation on pipelines.