just: A Command Runner for Your Project's Tasks
Every project ends up with a handful of commands everyone needs to remember: how to install dependencies, run the build, run the tests, start the dev server, cut a release. Those commands usually live in a README, a pile of shell scripts, or a package.json scripts block that only works for Node projects. just gives them a proper home.
just is a command runner — a single tool for saving and running project-specific commands from a file called a justfile. If you've reached for a Makefile to do this and fought with tabs, phony targets, and shell quirks, just is the purpose-built alternative: the same "run a named recipe" convenience, without the baggage.
What just is (and isn't)
just is not a build system. It won't track file timestamps or decide what needs recompiling the way make does. It does one thing well: it stores commands as named recipes and runs them. That narrow focus is the point — it's a friendlier, more predictable replacement for the way most teams (ab)use Makefiles as task runners.
It's a single Rust binary, works the same on macOS, Linux, and Windows, and is language-agnostic: the recipes inside can run anything.
Installing just
# macOS / Linux
brew install just
# Windows
winget install --id Casey.Just
# Any platform with Rust
cargo install just
Your first justfile
Create a file named justfile in your project root:
# install dependencies
install:
npm ci
# build the app (runs install first)
build: install
npm run build
# run the test suite (runs build first)
test: build
npm test
Now run recipes by name:
just build # runs install, then build
just test # runs install, build, then test
just # runs the first recipe (or the default)
just --list # show every available recipe
The test: build syntax declares a dependency: asking for test runs build first, which runs install first. You describe what depends on what once, and just resolves the order.
Recipes that take arguments
Recipes can accept parameters, which makes them far more flexible than a static script:
# deploy to a named environment
deploy target:
./scripts/deploy.sh {{target}}
just deploy staging
just deploy production
You can also define variables and reuse them:
node_env := "production"
build:
NODE_ENV={{node_env}} npm run build
Loading environment variables
just can load a .env file automatically so your recipes have the variables they need, without you exporting them by hand:
set dotenv-load
start:
node server.js # sees everything from .env
Keep real secrets out of a plaintext .env, though. For anything sensitive, encrypt your .env files with dotenvx and decrypt them at runtime rather than committing raw values.
Recipes in other languages
A recipe isn't limited to shell. With a shebang, it runs in whatever interpreter you name — handy for a quick script that would be awkward in bash:
count-files:
#!/usr/bin/env python3
import os
print(len(os.listdir(".")))
Using just with DeployHQ
Here's where just pays off for deployment specifically: the recipes you run locally are the exact commands your build pipeline should run. You've already written just build to mean npm ci && npm run build — so there's a single, version-controlled definition of how your project is built, and no drift between "what I run on my laptop" and "what the server runs."
There are two clean ways to wire that into DeployHQ:
- Mirror the commands. Copy the commands from your recipe into your project's build pipeline steps. The
justfilestays the human-friendly local entry point; the pipeline runs the same underlying commands. - Install just as a build step, then call the recipe directly, so both sides literally run the same recipe:
cargo install just
just build
Either way, once your build commands live in a recipe, enable automatic deployments so every push runs that same build and ships the result — the command you tested locally is the command that reaches production.
just vs a full task runner
If all you need is named commands with dependencies, just is hard to beat for simplicity. If you also want to manage the runtime versions those commands run against, or load per-project environment variables, a broader tool may fit better — you can define tasks alongside runtimes and env with mise in one file. Many teams happily use both: mise for versions and environment, just for the day-to-day command menu.
Ready to run the same build on your server that you run locally? Create a free DeployHQ account and connect your repository in minutes.