keyboard-shortcut
d

just use Just

3min read

an image

Just 👏 use 👏 Just

You have a Makefile. It has targets like test, deploy, serve. It works, but there are better options out there!

Make is a build tool

Make was built in 1976 to compile C programs. Its entire mental model is built around file targets: you describe how to build output files from input files, and Make figures out what needs rebuilding. That's genuinely brilliant for C compilation.

When you write make deploy, Make is looking for a file called deploy. It doesn't find one, so it runs the recipe, but only by accident. That's why .PHONY exists. You're not writing task runners, you're tricking a build system into running your tasks.

.PHONY: test deploy serve  # This exists because Make thinks these are files.

test:
    uv run pytest

deploy:
    ./deploy.sh

Just is purpose-built

Just is a task runner. That's it. No file targets, no .PHONY, no make-specific variable syntax. A justfile is a list of recipes. Recipes run commands. Done.

test:
    pytest

deploy:
    ./deploy.sh

No ceremony. No gotchas.

Flexible recipes

This is where Just earns its keep. Make's argument handling is awkward. You're passing variables, not arguments. Just treats recipes like functions.

deploy env="production":
    ./deploy.sh {{env}}

test *args:
    pytest -vx {{args}}

Args can be passed positionally or by name, and support defaults:

  • just deploy uses the default value "production"
  • just deploy staging passes positionally
  • just deploy env=staging passes by name

Variadic args let you tack on whatever pytest flags you need:

  • just test runs pytest -vx with no extras
  • just test -k simple narrows to matching tests
  • just test -k simple --tb=short adds a shorter traceback
  • just test --pdb drops into the debugger on failure

Compare that to doing the same in Make:

deploy:
    ./deploy.sh $(ENV)

test:
    uv run pytest -v $(ARGS)

Make uses environment-style variables instead:

  • make deploy ENV=production passes the env
  • make deploy runs with an empty string. Good luck.
  • make test ARGS="-k simple --pdb" works, but the whole string goes in one variable
  • make test runs pytest -v with an empty string at the end.

Named args with defaults. No silent failures. All information is in the recipe signature.

The verdict

If you're using Make as a task runner, and you almost certainly are, you've outgrown it. Just does the same job with less friction, better argument handling, and no historical baggage from 1976.

Your Makefile is a task runner pretending to be Make. Just is honest about what it is.

Just use Just.