If you copy long commands out of a README every time, a single Makefile tidies that up. Make exists on every Unix-like system and doesn’t care what language you write in.

A minimal Makefile

Makefile at the project root (tab indentation is mandatory):

  .PHONY: help install dev test lint build clean

help:  ## Show the available commands
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
	  awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[36m%-12s\033[0m %s\n", $$1, $$2}'

install:  ## Install dependencies
	npm ci

dev:  ## Run the development server
	docker compose up -d
	npm run dev

test:  ## Run the tests
	npm test

lint:  ## Lint and check formatting
	npm run lint
	npm run format:check

build:  ## Production build
	npm run build

clean:  ## Remove build output
	rm -rf dist node_modules/.cache
	docker compose down
  

make or make help prints the commands with their descriptions, so a new teammate can see what’s possible without reading the README.

Syntax to know

SyntaxMeaning
.PHONY: nameAlways run, even if a file of that name exists
target: depsRun the dependency targets first
@commandDon’t echo the command itself
-commandContinue even if it fails
$$A literal $ for the shell (distinct from Make’s $)
VAR ?= valueKeep an existing definition

Indentation must be tabs. Spaces produce Makefile:5: *** missing separator. Configure your editor to preserve tabs in Makefiles ([Makefile] indent_style = tab in .editorconfig).

Variables and arguments

  ENV ?= dev
IMAGE = myapp:$(ENV)

build:
	docker build -t $(IMAGE) .

deploy:
	./deploy.sh $(ENV)
  
  make deploy ENV=prod
  

Each line is its own shell

  # wrong — the cd does not carry to the next line
wrong:
	cd src
	npm test

# right
right:
	cd src && npm test
  

Alternatives

ToolCharacter
justNone of Make’s traps (tabs, separate shells). Uses a justfile
npm scriptsAlready there in a Node project; strains as things grow
TaskfileYAML based, with dependencies and conditions
  brew install just
just --list
  

Make’s biggest advantage is that it is already installed everywhere. Pick Make when not requiring a new install matters, and just when syntax comfort wins.

Next

For work that has to run at a set time → cron and launchd

Last updated 19 Aug 2026, 00:00 UTC. history