`just` — the command runner for projects without a package.json

Today I Learned · October 8, 2026

just — the command runner for projects without a package.json

TypeScript projects get package.json — a place to write npm run lint once and reuse it forever. Most other ecosystems get nothing: the formatting, lint, seed, migrate, rollback, and cleanup commands you run are whatever you can dig out of shell history, and editing them means re-editing history again. just is a command runner written in Rust that fixes this with a justfile — a Makefile-inspired file of named recipes you invoke like normal commands.

set shell := ["bash", "-uc"]

cc    := "g++"
flags := "-std=c++23 -Wall -Wextra -O2"
db    := "portfolio"

# build <target>: compile src/<target>.cpp into bin/
build name:
    {{cc}} {{flags}} -o bin/{{name}} src/{{name}}.cpp

# compile, then run it
run name: build name
    ./bin/{{name}}

# formatting and linting, batched
fmt:
    clang-format -i src/*.cpp

lint:
    clang-tidy src/*.cpp

check: fmt lint

# database chores, parameterized
migrate direction='up':
    psql -d {{db}} -f migrations/{{direction}}.sql

seed:
    python3 scripts/seed.py

clean:
    rm -rf bin/

The compile command that used to be a multi-line string you’d search history for and hand-edit every time is one word now: just build main.

Reading the pieces

Piece Job
build name: a recipe named build that takes one parameter
{{name}} interpolates the parameter into the command
run name: build name run depends on build — dependencies run first
migrate direction='up': a parameter with a default, so just migrate down still works
# comment above a recipe becomes its description in just --list
set shell := [...] the shell every recipe line is evaluated in
cc := "g++" a variable; reuse the command once at the top

Why this beats history-diving

Choosing a shell

The default shell is sh -cu, and you don’t have to keep it. set shell := ["bash", "-uc"] swaps in bash if you want its globbing and control flow (note the -c argument — just hands each line to the shell via -c). The [unix] and [windows] attributes let one justfile pick per-OS shells and commands, which is how the same file works on Linux, macOS, and Windows:

[windows]
set shell := ["powershell.exe", "-NoLogo", "-Command"]

[unix]
set shell := ["bash", "-uc"]

Gotchas

Install it with cargo install just, or via your package manager (apt, brew — it’s everywhere, one binary, no dependencies).