The goal is a single source of truth for "how do I do X in this repo" that anyone can read and understand.
<quick_start> <core_rule> Justfiles always run from the repo root. Never cd in recipes. Use absolute paths or paths relative to the justfile location. </core_rule>
<basic_structure>
Group: Development
dev: npm run dev
Group: Testing
test: npm test
test-watch: npm test -- --watch
</basic_structure> </quick_start>
<essential_principles>
Always run from root, never cd
Justfiles execute from the repository root. This is a feature, not a limitation:
-
Predictable behavior regardless of where you invoke just
-
Paths in recipes are always relative to repo root
-
No confusion about "where am I running this from"
Good - explicit path from root
build: cd packages/app && npm run build
Bad - assumes current directory
build: npm run build
If a command needs to run in a subdirectory, use cd dir && prefix explicitly.
The justfile should be the single source of truth for repo commands. If someone asks "how do I run tests?" or "how do I deploy?", the answer is in the justfile.
Instead of remembering: npm run test:unit -- --coverage --reporter=html
test-coverage: npm run test:unit -- --coverage --reporter=html
Instead of remembering: docker compose -f docker-compose.dev.yml up -d
dev-services: docker compose -f docker-compose.dev.yml up -d
Benefits:
-
No tribal knowledge ("oh you need to pass --reporter=html")
-
Commands are documented by their existence
-
Easy to discover: just --list
Use comments to create visual groupings. Let the groups emerge from your actual commands:
─────────────────────────────────────────────────────────────
Development
─────────────────────────────────────────────────────────────
dev: npm run dev
─────────────────────────────────────────────────────────────
Testing
─────────────────────────────────────────────────────────────
test: npm test
test-watch: npm test -- --watch
Common groupings (adapt to your project):
-
Setup / Installation
-
Development
-
Testing
-
Building
-
Deployment
-
Database / Migrations
-
Utilities / Helpers
Justfiles replace scattered shell commands and npm scripts for common operations. They don't replace:
-
Build tool configuration (webpack, vite, etc.)
-
CI/CD pipeline definitions
-
Complex scripting (use actual scripts in scripts/ )
Rule of thumb: If a recipe is longer than 5-10 lines, extract it to a script file and call that from the justfile:
Good - justfile calls the script
deploy: ./scripts/deploy.sh
Avoid - complex logic inline
deploy: if [ "$ENV" = "prod" ]; then # ... 20 lines of logic fi
Use recipe names that describe the workflow, not the tool:
Good - describes what you're doing
setup: npm install cp .env.example .env just db-migrate
Less good - just wraps the tool
npm-install: npm install
Chain related commands with dependencies:
Running just deploy runs lint, test, build first
deploy: lint test build ./scripts/deploy.sh
The first recipe (or one named default ) runs when you type just just :
Show available commands by default
default: @just --list
Or start development by default
default: just dev
Positional argument
test file: npm test {{file}}
With default value
build env="dev": npm run build -- --env={{env}}
Variadic arguments
run *args: npm run {{args}}
From .env file
set dotenv-load
Inline variable
db_name := "myapp_dev"
Recipe-local export
migrate: export DATABASE_URL=$DATABASE_URL && npm run migrate
[confirm("Are you sure you want to reset the database?")] db-reset: dropdb myapp && createdb myapp && just db-migrate
Prefix with _ to hide from just --list :
Public - shows in list
build: _check-deps npm run build
Private - hidden helper
_check-deps: @command -v node >/dev/null || (echo "Node required" && exit 1)
Deploy to production (requires VPN connection)
[doc("Deploy the application to production environment")] deploy-prod: ./scripts/deploy.sh prod
<anti_patterns>
Avoid changing directory implicitly
Bad - unclear where this runs
build: cd src npm run build
Good - explicit and stays in root
build: cd src && npm run build
If npm run dev is obvious and memorable, you don't need just dev unless it adds value (like running setup first).
Add justfile recipes when:
-
The command has flags that are hard to remember
-
Multiple commands need to run together
-
The command needs environment setup
Before: Developers need to know npm, docker-compose, aws, terraform, kubectl...
After: just --list shows everything, actual tools are implementation details.
These hide complexity behind simple names
deploy: terraform apply -auto-approve
db-shell: kubectl exec -it postgres-0 -- psql
<success_criteria> A well-organized justfile:
-
Runs all commands from repo root (no implicit cd)
-
Has logical groupings with clear visual separation
-
Captures common commands as aliases (single source of truth)
-
Uses descriptive recipe names (workflow-focused, not tool-focused)
-
Keeps recipes short (complex logic in scripts/)
-
Has a sensible default recipe
-
Is discoverable via just --list
</success_criteria>