Skip to content

Just: A Command Runner for Project Recipes

DodaTech Updated 2026-06-22 6 min read

In this tutorial, you'll learn Just command runner including recipes, dependencies, variables, shebang recipes, and using Just for project-specific commands across different languages and tools.

Why Just Matters

Every project has repetitive commands: running tests, building, deploying, cleaning up. Make has been the go-to tool for decades, but its arcane syntax and tab requirements make it error-prone. Taskfile is great but requires YAML indentation discipline. Just strikes a balance: a clean, Make-like syntax with better defaults, cross-platform support, and no tab requirements.

By the end of this guide, you will write Justfiles for any project, use recipes with dependencies, variables, and shebangs, and integrate Just into your development workflow.

What is Just?

Just is a command runner written in Rust. It uses a Makefile-like syntax but avoids Make's quirks. Recipes are indented with spaces, not tabs. Justfiles are cleaner, more readable, and work the same on Linux, macOS, and Windows.

flowchart LR
  A[Justfile] --> B[Recipes]
  B --> C[build]
  B --> D[test]
  B --> E[deploy]
  C --> F[dependencies: install]
  C --> G[commands]
  E --> H[commands: rsync, ssh]
  F --> I[recipe: install]
  I --> J[commands: npm install]

Installation

# macOS
brew install just

# Linux (pre-built binary)
curl -fsSL https://just.systems/install.sh | bash

# Verify
just --version
# just 1.35.0

Your First Justfile

# Justfile
hello:
  echo "Hello, Just!"
just hello

Expected Output

echo "Hello, Just!"
Hello, Just!

Run silently:

hello:
  @echo "Hello, Just!"
$ just hello
Hello, Just!

Recipes with Dependencies

install:
  npm ci

build: install
  npm run build

test: install
  npm test

lint: install
  npm run lint

all: build test lint
just build
# Runs install first, then build

Variables

name := "myapp"
version := "1.0.0"
build_dir := "dist"
go_flags := "-ldflags=-s -w"

build:
  mkdir -p {{build_dir}}
  go build {{go_flags}} -o {{build_dir}}/{{name}} .

test:
  go test -v ./...

clean:
  rm -rf {{build_dir}}

Overriding Variables

just version=2.0.0 build

Default Values

image := "myapp"
tag := tag or "latest"

push:
  docker push {{image}}:{{tag}}

Shebang Recipes

Shebang recipes use a different Interpreter for the recipe body.

# Shebang recipe using Python
analyze-logs:
  #!/usr/bin/env python3
  import sys
  for line in sys.stdin:
      parts = line.strip().split()
      if len(parts) > 0:
          print(parts[0])

# Shebang recipe using Node.js
format-json:
  #!/usr/bin/env node
  const data = require('fs').readFileSync('/dev/stdin', 'utf8');
  console.log(JSON.stringify(JSON.parse(data), null, 2));
cat log.txt | just analyze-logs
cat data.json | just format-json

Recipe Parameters

greet name:
  @echo "Hello, {{name}}!"

build target="release":
  @echo "Building {{target}} mode..."
  if [ "{{target}}" = "release" ]; then
    cargo build --release
  else
    cargo build
  fi
just greet Alice
just build debug

Cross-Platform Support

# Cross-platform commands
clean:
  -rm -rf {{build_dir}}  # Linux/macOS

clean-win:
  -rm -rf {{build_dir}}  # Windows (using shell)

clean-all: clean clean-win

# OS-specific variables
node_bin := if os == "windows" { "node.exe" } else { "node" }

check-node:
  @which {{node_bin}}

Real-World Justfiles

Rust Project

crate := "myapp"
version := "0.1.0"

build:
  cargo build

release:
  cargo build --release

test:
  cargo test

lint:
  cargo clippy -- -D warnings

fmt:
  cargo fmt

doc:
  cargo doc --no-deps

clean:
  cargo clean

run:
  cargo run

bench:
  cargo bench

dev: build run

React Project

build_dir := "dist"

install:
  npm ci

dev: install
  npm run dev

build: install
  npm run build

test: install
  npm test

lint: install
  npm run lint

typecheck: install
  npx tsc --noEmit

preview: build
  npx serve {{build_dir}}

deploy: build
  rsync -avz {{build_dir}}/ user@server:/var/www/app/

Multi-Language Project

export DATABASE_URL := "postgresql://localhost:5432/myapp"

# Backend tasks
backend-install:
  cd backend && pip install -r requirements.txt

backend-dev: backend-install
  cd backend && uvicorn main:app --reload

backend-test: backend-install
  cd backend && pytest -v

backend-migrate: backend-install
  cd backend && alembic upgrade head

# Frontend tasks
frontend-install:
  cd frontend && npm ci

frontend-dev: frontend-install
  cd frontend && npm run dev

frontend-build: frontend-install
  cd frontend && npm run build

# Combined tasks
install: backend-install frontend-install

dev:
  @echo "Starting development servers..."
  cd backend && uvicorn main:app --reload &
  cd frontend && npm run dev

test: backend-test frontend-test

Justfile Organization

# Justfile
alias d := dev
alias b := build
alias t := test

# --- Development ---
dev:
  cargo run

# --- Build ---
build:
  cargo build --release

# --- Testing ---
test:
  cargo test

# --- Documentation ---
doc:
  cargo doc --no-deps --open

# --- Maintenance ---
update:
  cargo update

outdated:
  cargo outdated

Conditionals and Settings

# Justfile settings
set dotenv-load := true
set positional-arguments := true

# Conditional execution
test:
  cargo test
  if [[ "{{os}}" == "linux" ]]; then
    cargo test --features=linux-only
  end

export CI := "true"

ci: test lint build

Comparison

Feature Just Make Task
Syntax Make-like, clean Makefile (tabs) YAML
Cross-platform Good Poor Excellent
Parameters Yes Limited Variables only
Shebang recipes Yes No No
Dependencies Yes (after :) Yes (after :) Yes (deps array)
Default recipe First recipe First target default task
Speed Fast (Rust) Fast (C) Fast (Go)

Common Errors

Problem Cause Fix
Justfile:1: error: Expected a recipe Invalid syntax Check that the first non-comment line starts with a recipe name
error: Recipe test not found Recipe name misspelled Check spelling in command and Justfile
Justfile:5: error: Expected ':' Missing colon after recipe name Every recipe needs : after its name
Shebang recipe not working Missing shebang line First line after recipe must be #!/usr/bin/env <a href="/design-patterns/interpreter/">Interpreter</a>
Variable NAME not interpolated Wrong syntax Use {{NAME}} not $NAME in justfiles

Practice Questions

1. What is the syntax for a Just recipe with dependencies?

build: install means build depends on install.

2. How do you pass parameters to a Just recipe?

Define them in the recipe header: greet name: and call with just greet Alice.

3. What is a shebang recipe?

A recipe that uses a different Interpreter (Python, Node.js, etc.) for the body.

4. How do you reference a variable in a Justfile?

{{variable_name}}.

5. How do you run a recipe silently (no command echo)?

Prefix the command with @.

Challenge

Create a Justfile for a full-stack project with Node.js frontend and Python backend. Include recipes for: installing all dependencies, running both dev servers in parallel, running all tests, linting all code, building for production, deploying, and cleaning up. Use shebang recipes for at least one data-processing task.

Real-World Task

Migrate an existing project's build commands from npm scripts, Makefile, or shell scripts to a Justfile. Create recipes that match every workflow you use daily. Add parameters for environment-specific configuration (development, staging, production). Test that the Justfile works on both Linux and macOS.

Should I use Just or Task?

Both are excellent. Just has a simpler syntax closer to Make, making it a gentler Migration path. Task has YAML, which is better for complex configurations with many variables.

Can Just read environment variables?

Yes. Use set dotenv-load := true to load .env files. Access environment variables with {{env(\"VAR\")}}.

{{< faq "Is Just available on Windows?">}} Yes. Just supports Windows natively, though some shell commands may differ. Use set shell := ["<a href="/microsoft-technologies/powershell/">PowerShell</a>", "-c"] for PowerShell recipes.{{< /faq >}}

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro