Every project eventually grows its own mythology. “How do you run the tests?” becomes a question answered with a message, a README with outdated instructions, or, if you’re truly cursed, a tribal elder who just left the company.

just ends this. It’s a command runner that stores your project’s commands in a justfile, right next to your code, where they belong.

The problem it solves Link to heading

You know the moment. New repo, zero context. You type npm start and get a cryptic error, try npm run dev, and get nothing. Digging through package.json scripts turns up a command called go:brrrr. You close the laptop and reconsider your career choices.

A justfile is a social contract: here are the commands, here’s what they do, and you run them without ceremony.

It’s a generational improvement over Makefiles, and it makes your life better. My first job in the stone age was maintaining a Makefile that gave me actual nightmares — justfiles help.

Install it Link to heading

brew install just  # macOS
choco install just # Windows
cargo install just # Linux

That’s it. It just works, which feels on-brand.

Your first justfile Link to heading

# Show available commands (great as a default)
default:
    just --list

# Start the dev server
dev:
    npm run dev

# Run tests
test:
    vitest run

# Build for production
build:
    npm run build

Save as justfile in your project root, then:

just dev
just test
just build

Someone joins your team and immediately knows how to use the project. You’ve prevented at least three messages and a passive-aggressive comment in a PR.

It handles arguments Link to heading

# Deploy to a specific environment: just deploy prod
deploy env:
    echo "Deploying to {{env}}..."
    fly deploy --env {{env}}
just deploy staging
just deploy prod

No more wrapping bash -c 'ENV=staging ./deploy.sh' in a shell alias you’ll forget exists.

It loads your .env Link to heading

set dotenv-load

db-connect:
    psql $DATABASE_URL

Pop DATABASE_URL in your .env file and just db-connect picks it up automatically. No source .env && prefix required. You’re welcome.

Recipes can depend on each other Link to heading

build:
    npm run build

test: build
    vitest run

ci: test
    echo "Ship it."

just ci runs test, which first runs build. It’s dependency management for your workflow, and unlike most dependency management, it doesn’t make you want to cry.

Groups help discovery Link to heading

Groups make life simple and are trivial to set up. Here’s the output of asking the agent to organise the recipes into groups: build, ci, lint & format, and security.

Available recipes:

    [Build]
    build             # lineup changes (e.g. "iPhone 16 Pro" no longer exists on newer Xcode).
    clean             # Remove build artifacts, including DerivedData for this project

    [CI]
    ci                # Full pre-commit/CI gate: lint, format check, build, test

    [Lint & Format]
    format            # Reformat Swift source (requires swiftformat; see `just tools`)
    lint              # Lint Swift source (requires swiftlint; see `just tools`)
    lint-fix          # Auto-fix lint violations where safe

    [Security]
    analyze           # Run the Clang static analyzer over the app target
    scan-secrets      # Scan for leaked secrets/keys/tokens with betterleaks

Why not Makefile? Link to heading

The Makefile is a venerable, respected tool, but to me in 2026 it feels historic. It was designed for building C programs in the 1970s. Using it as a command runner requires declaring .PHONY targets and fighting with tabs-vs-spaces in ways that will drive you mad. They can be turned into things of beauty, but take a lot of code to get there.

The real win Link to heading

I like just because of the quality-of-life features and because of the convention. When every project has a justfile, you stop thinking about how to run things. On a new repo, just --list gets you productive in 30 seconds.

Your justfile stays accurate because it’s the commands people actually run, not a description of them written down somewhere else — and that’s what makes working on the project a joy.

# Note: This takes 4 minutes because Jenkins hates us
deploy-prod:
    ./scripts/deploy.sh production

Even the annoying bit about Jenkins taking four minutes is captured right there, for the next person who runs it.

Question Link to heading

Should your pre-commit hooks reference your justfile, or be written out separately? I don’t have a strong opinion, but I lean towards referencing the justfile to avoid duplication. Thoughts?