The platform team is standardising the entry point for every repository's onboarding — bootstrap, doctor, db-reset — and cannot agree on the tool. Make is already everywhere but produces the classic *** missing separator and .PHONY bugs; just is friendlier but not preinstalled; Task runs natively on Windows but is YAML. Abstract comparisons have not settled it. This page writes the same three onboarding tasks in all three tools so the trade-offs are visible in real code, as part of task runners and an internal developer CLI.

The tasks are deliberately ordinary: a bootstrap that installs dependencies and starts services, a doctor that checks tools, and a destructive database reset that should confirm first.

Diagnostic

Before choosing, list what the team's machines already have and which platforms must be supported — this decides more than syntax preferences do:

#!/usr/bin/env bash
set -euo pipefail
printf 'os=%s arch=%s\n' "$(uname -s)" "$(uname -m)"
for t in make gmake just task bash pwsh; do
  if command -v "$t" >/dev/null; then printf '%-6s %s\n' "$t" "$("$t" --version 2>&1 | head -1)"; else printf '%-6s missing\n' "$t"; fi
done

Typical results across a mixed team:

macOS:    make GNU Make 3.81 | just missing | task missing | bash 3.2.57
Linux:    make GNU Make 4.3  | just missing | task missing | bash 5.2.21
Windows:  make missing       | just missing | task missing | pwsh 7.4.5

Make is present on macOS and Linux but in two very different versions, nothing is present on Windows, and macOS ships Bash 3.2, which lacks associative arrays and other features scripts often assume.

What Each Platform Has by Default Table of which task runners and shells are preinstalled on macOS, Linux and Windows. What Each Platform Has by Default Platform make just, task shell macOS 3.81 no bash 3.2, zsh Linux 4.x no bash 5 Windows no no PowerShell
Only Make is preinstalled anywhere, and never on Windows; every option needs one install step somewhere.

Root cause

The three tools differ because they were built for different jobs. Make is a build system: it models files and their dependencies, and task running is a side use that inherits file semantics (.PHONY), strict syntax (tabs) and awkward argument handling. just is a command runner only: it drops file semantics, adds parameters, groups, confirmations and a self-documenting list, and runs recipes in whatever shell you configure. Task is also a command runner, configured in YAML, with a portable embedded shell and optional file-fingerprint checks. None is wrong; the choice depends on whether you need file-based skipping, how much Windows matters, and how much the team values readable task files over zero installation.

Resolution

  1. Read the same tasks in each tool. In Make:
.PHONY: bootstrap doctor db-reset
SHELL := bash
.SHELLFLAGS := -euo pipefail -c

bootstrap: ## Install deps and start services
	npm ci
	docker compose up -d --wait

doctor: ## Check required tools
	./scripts/doctor.sh

db-reset: ## Drop and reseed the local database (asks first)
	@read -r -p "Delete local database? [y/N] " ans && [ "$$ans" = y ]
	docker compose rm -sfv db
	docker compose up -d --wait db
	npm run db:seed

help: ## List tasks
	@grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf "%-12s %s\n", $$1, $$2}'

In just:

set shell := ["bash", "-euo", "pipefail", "-c"]

# Install deps and start services
bootstrap:
    npm ci
    docker compose up -d --wait

# Check required tools
doctor:
    ./scripts/doctor.sh

# Drop and reseed the local database
[confirm('Delete local database?')]
db-reset:
    docker compose rm -sfv db
    docker compose up -d --wait db
    npm run db:seed

In Task:

version: '3'
tasks:
  bootstrap:
    desc: Install deps and start services
    sources: [package-lock.json]
    generates: [node_modules/.package-lock.json]
    cmds:
      - npm ci
      - docker compose up -d --wait
  doctor:
    desc: Check required tools
    cmds:
      - ./scripts/doctor.sh
  db-reset:
    desc: Drop and reseed the local database
    prompt: Delete local database?
    cmds:
      - docker compose rm -sfv db
      - docker compose up -d --wait db
      - npm run db:seed
  1. Compare on the points that caused real tickets. Make needs $$ escaping, a custom help target and a hand-written confirmation; just and Task have built-in listing and confirmation. Only Task's bootstrap skips npm ci when the lockfile has not changed. Only Task runs rm-style commands on Windows without Bash.

  2. Decide with a simple rule:

    • Mostly macOS/Linux, file builds matter → keep Make, add the help pattern and .PHONY discipline.
    • Mostly macOS/Linux, task running only → just.
    • Native Windows developers, or skipping expensive steps matters → Task.
  3. Pin whichever you choose in the repository's toolchain file and install it in the bootstrap script, so "not preinstalled" costs one line once.

just vs Task for Onboarding Tasks Comparison of just and Task on syntax, listing, confirmation, skipping and Windows. just vs Task for Onboarding Tasks just Task Make-like syntax YAML just --list from comments task --list from desc [confirm] attribute prompt field no up-to-date checks sources and generates needs a shell on Windows embedded shell
Both remove Make's pitfalls; Task adds skipping and native Windows at the cost of YAML.

Expected output

Whichever tool is chosen, the listing a new hire sees on day one should look like this:

$ just --list
Available recipes:
    bootstrap # Install deps and start services
    db-reset  # Drop and reseed the local database
    doctor    # Check required tools
$ task --list
task: Available tasks for this project:
* bootstrap:       Install deps and start services
* db-reset:        Drop and reseed the local database
* doctor:          Check required tools

A discoverable, described list is the practical outcome that matters; with Make it takes the custom help target to get the same result.

It is worth doing this exercise with the team's real tasks rather than the toy versions here. Porting ten or fifteen actual tasks usually takes an afternoon per tool and surfaces the specific friction points — a task that needs to cd and keep state, one that parses arguments, one that must run on a Windows laptop — which then decide the question far more convincingly than a feature table.

Prevention

  1. Write the choice down in the contributing guide with the reason, so the debate does not restart with each new hire.

  2. Use the same verbs across repositories regardless of tool. bootstrap, doctor, test, lint, db-reset should mean the same thing everywhere; the tool is an implementation detail.

  3. Check the listing in CI. Fail if any public task has no description, which keeps the onboarding surface complete in all three tools.

Picking the Tool for a Repository Decision diagram choosing make, just or Task from platform mix and need for file-based skipping. Picking the Tool for a Repository Do developers use native Windows? Yes Task No, need file builds make No, tasks only just
Platform mix first, then whether skipping work on unchanged inputs matters.

Platform caveats

macOS: GNU Make 3.81 lacks .ONESHELL and --output-sync; write Makefiles to that version or install GNU Make 4 from Homebrew and document gmake. Bash 3.2 lacks associative arrays; set just's shell to zsh or a Homebrew Bash if recipes need them.

Windows (native): Make needs a POSIX environment such as MSYS2; just needs Git Bash or a windows-shell setting for PowerShell; Task runs its embedded interpreter without extra installs.

WSL2: all three behave as on Linux. If the team standardises on WSL2 for Windows developers, the Windows row of the decision disappears.

Apple Silicon (ARM64): just and Task have native arm64 builds in Homebrew; the system Make is universal.

Rollback

Switching tools is a matter of keeping a forwarding shim for a few weeks and reverting if needed:

#!/usr/bin/env bash
set -euo pipefail
git log --oneline -3 -- Makefile justfile Taskfile.yml
git revert --no-edit HEAD

Frequently Asked Questions

Which one should a new project use?

If the team is on macOS and Linux and only needs task running, just is the most pleasant. If native Windows matters or tasks should skip unchanged work, use Task. If the project builds files from files, Make remains the right tool for that part.

Can we use npm scripts instead?

In JavaScript-only repositories, yes. In polyglot repositories, npm scripts are awkward for non-Node tasks and do not document themselves well; a task runner that calls npm scripts where useful works better.

Is YAML a problem for Task files?

It mainly affects readability of long shell commands, which need quoting or block scalars. Keeping task bodies short and moving logic into scripts avoids most of the pain.

Does the choice affect CI?

Only in installation. Each tool has a setup action or can be installed in one line; CI then calls the same tasks developers run, which is the important part.