FrankWiles.com

/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:

Image of zsh shell showing just help output

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:

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.

shell
$ 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.

CommandDescription
just rebuildRebuild all Docker containers
just testRun the full test suite
just test tests/test_models.pyRun only the tests in this file one file
just shellExec into the main app container and get shell
just build <version>Build a new Docker image and tag it with <version>
just devRun k9s --context client-dev-cluster --namespace dev
just prodRun k9s --context client-prod-cluster --namespace prod
just bootstrapPrep your local environment the first time
just lintRun all linting
just lockRun uv pip compile ... in the app container
just lock --upgradeRun uv pip compile --upgrade ... in the app container
just rebuild_indexRun 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.

Image of zsh shell showing just help output for a larger project

Installing just

The easiest way for most people to install just is to use Homebrew or via Rust’s cargo

Homebrew

shell
$ brew install just 

Cargo

shell
$ 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

Headshot of Frank Wiles

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.