I've tried the "just" task runner. Is it worth it?
I was initially sceptical about just task runner. I wasn’t really convinced that it’s a tool solving a real problem and thought of it more as a gimmick. Finally, I decided to give it a try to form a more informed opinion. Below are some of my observations.
It’s just a command executor
In essence, that’s everything just is. You create a justfile
in which
you define tasks. Each task is a set of steps. Each step is executed in a
separate shell instance. It’s possible to define dependencies between tasks.
Here’s a basic justfile
example:
|
|
Tasks from this file can be executed like so:
|
|
We all write either shell scripts or simple Makefiles
just to make it more
convenient to perform a common tasks within a project. The syntax is almost
identical as in Makefile
with a small important difference. make
operates
in terms of targets - this means that each target is meant to produce a
tangible deliverable. In subsequent runs, make
checks for presence of a
target’s deliverable. Target’s absence triggers recipe execution. Recipe will be executed
as well if the target is older than any of its source files - we all know how
Makefiles work. That’s not the case with just
.
--no-deps
switch.That’s the main difference between make
and just
. The former is a build
system, the latter is just a task executor. Subtle, but very important. If a
task has dependencies - they will be run prior to the task itself.
What’s the extra value over Makefiles or shell scripts?
To me, it’s all in --no-deps
. This flag gives you full control over how
tasks are executed and is the main convenience that just
brings to the table.
If you’re writing a shell script, the dependencies are rigid and can’t be dynamically altered.
|
|
Without modifying the script, it’s impossible to skip some steps. Similarly,
in case of a Makefile
. Having a justfile
:
|
|
You have full control over what to run:
|
|
Listing the contents
Often you just want to see a list of targets within a Makefile. Without
opening the Makefile, it’s difficult to establish that (although this has
recently changed. SV
64571
adds --print-targets
to make
). With just
you can
simply:
|
|
It’s even easier if you add a private (prefixed with _
) default task to your justfile
:
|
|
just
runs the default
recipe if none is provided in the command line:
|
|
Working directory
By default, recipes run with the working directory set to the directory that
contains the justfile
. This is great and a great improvement. I often find
myself writing the following lines in my shell scripts:
|
|
With just
I no longer have to do that as the working directory for each task
is well defined.
Variables
just
allows for definition of global variables. Task steps run in
independent shells so, the variables have to be global (there’s a workaround
for that). These variables can be exported to environment with:
set export
Additionally, just
automatically consumes .env
files with
set dotenv-load
Tasks can be parametrised (and parameters can have default values):
|
|
The variables can be overridden in the command line:
|
|
Positional parameters are supported too! There’s plenty more which I won’t cover since the documentation does that very well.
Shell scripts in tasks
As I already mentioned, each task step runs in an independent instance of a shell. The shell can be anything you want though:
|
|
Additionally, to preserve context between steps, tasks can be defined as a scripts:
|
|
Conclusion
I won’t hide that I was initially sceptical about just
, assuming there’s little
value that it adds, but after using it for a while, I must admit that it’s a
great addition to my daily workflow. It’s a perfect replacement for clunky
Makefiles meant to simplify some of the commands and feels more suitable for
exactly that purpose.