/usr/bin/just do it
When working on projects of any real size you end up with a few to a few dozen project specific commands. You might call them commands, recipes, or scripts. You may have implemented them in Bash, a Makefile or folder full of a hodgepodge of various languages.
I’m here to tell you that you should be doing all of this with just instead.
As a consultant for 18 years, I work on dozens of very different projects each year and
just
is one of those tools that improves each one. It’s a bonus that it is very easy to incorporate!
Let’s dive into a small simple example that is a bit silly.
Silly Example
We define our recipes in a file named Justfile
or justfile
.
@default:
just --list
# Get sued
@do it:
echo "We're going to do {{it}}"
echo "P.S. Nike, please don't sue me"
I like to make the default command, the one run if you don’t give it a specific command to list all of the commands we’ve defined. This is the built in help I mentioned earlier.
If you don’t do this, the first command defined in your file becomes the default command which can be dangerous if it’s at all destructive.
If we run just
with no options we now see this:

It is hard to make out with my shell’s color theme, but the it
is a very light blue color to indicate that it is an
argument of the do
recipe. The simple comment above acts as our documentation to the right.
Now if we run just do it
we’ll have the following output:
We're going to do it
P.S. Nike, please don't sue me
And if we run just do something
we get:
We're going to do something
P.S. Nike, please don't sue me
Oh, in case you prefer videos to blog posts here you go!
Why just?
Here is a quick TL;DR of why you should be using the just command runner if you are in a hurry:
- It’s wicked fast and the syntax is simple
- Built in help for your commands
- Makes it easy to accept and use arguments
- Recipes are composable and can call dependent recipes
- You can write your recipes in a variety of languages if you wish
- Shield your team from the minutae of a command and how it may need to change over time
- Shell autocompletion of your custom recipes
So why wouldn’t you want to use just? If you need make
, use make
obviously, but if you are not building a C/C++
project it’s actually a really crappy command runner with esoteric syntax (tabs vs spaces, PHONY
, etc). Honestly, the
best reason I can come up with NOT using just
to run commands is that, much like the Go programming language, it’s
difficult to Google search about!
More justification
Here are some other aspects of just
that I personally love and find incredibly useful in our software development and
devops projects.
For starters, the just
binary looks above/behind your current location in your folder structure for the closest Justfile
it can find.
So you don’t have to cd ../../../
up to the root of your project. The recipes you write also assume you want to
run them from the perspective of the directory containing the Justfile
, but you can override that easily for cases
where you want it to use your actually current working directory.
You can group recipes together which is useful as your number of recipe commands grows over time. You can easily segment local dev items from things you run in CI to things you run in production for example.
There are extensions for all of your favorite editors to handle syntax highlighting in case you were worried about that.
Standardization
Since we work on several projects at the same time having just up
do the same thing on each one, i.e. “bring the
project up locally for development” is less friction than having to remember for Project A it’s docker compose up
and
Project B it needs to be docker compose --profile=backend up
.
Ability to ignore
In a few projects I’ve built a pair of recipes snapshot-db
and restore-db
which reach out to a remote system,
grab a backup of the database, and then restore it into our local compose environment. My teammates only need to know
which environment they want to snapshot and a name that is meaningful to them.
$ just snapshot-db prod prod-april-27-2025
# ... Time passes as it dumps the database and transfers ...
$ just restore-db prod-april-27-2025
They do not need to be concerned with HOW those commands work and most importantly do not need to be informed or
learn a new process if how we do it changes over time. Next time they git pull
the get the new process.
Ideas for commands to create
I find it useful to think about how my team and I might use tools like this before investing the time to learn them and switch. Here is a large sample of commands we have in real world projects.
Command | Description |
---|---|
just rebuild | Rebuild all Docker containers |
just test | Run the full test suite |
just test tests/test_models.py | Run only the tests in this file one file |
just shell | Exec into the main app container and get shell |
just build <version> | Build a new Docker image and tag it with <version> |
just dev | Run k9s --context client-dev-cluster --namespace dev |
just prod | Run k9s --context client-prod-cluster --namespace prod |
just bootstrap | Prep your local environment the first time |
just lint | Run all linting |
just lock | Run uv pip compile ... in the app container |
just lock --upgrade | Run uv pip compile --upgrade ... in the app container |
just rebuild_index | Run the commands necessary to rebuild the search index |
Here is a screenshot of the just help output from a larger project to give you an idea of many different commands we usually end up defining.

Installing just
The easiest way for most people to install just is to use Homebrew or via Rust’s cargo
Homebrew
$ brew install just
Cargo
$ cargo install just
Conclusion and Thanks
Hopefully this post has intrigued you enough to give just a try.
Many thanks to Jeff Triplett who introduced me and everyone at REVSYS
to just
. We’ve standardized all of our projects with it over the last several
years and we couldn’t be happier about it.
If you like the general concept, but aren’t loving just
for whatever reason
awhile back Harper Reed recommended mise
to us. It has similar task running features but goes further and can handle
things like different environment variables like direnv.
Resources

Frank Wiles
Founder of REVSYS and former President of the Django Software Foundation . Expert in building, scaling and maintaining complex web applications. Want to reach out? Contact me here or use the social links below.