
Justfile: Task runner đơn giản thay thế Makefile và script shell
Justfile (câu lệnh just) là task runner hiện đại được viết bằng Rust, thay thế Makefile, npm scripts, bash script với cú pháp rõ ràng, hỗ trợ tham số, biến môi trường và cross-platform. Với 25.000+ stars trên GitHub và được sử dụng bởi hàng ngàn dự án open source (Rust, Go, Node.js), Justfile đang trở thành tiêu chuẩn cho việc tự động hóa quy trình build, test, deploy trong team dev.
Khác với Makefile (40 năm tuổi, cú pháp dựa trên tab, chỉ chạy trên Unix), Justfile chạy được trên Windows, macOS, Linux, hỗ trợ comment, string interpolation, điều kiện if/else, và tích hợp sẵn với shell completion.

Tại sao chọn Justfile?
- Cú pháp đơn giản: Giống Makefile nhưng không yêu cầu tab, hỗ trợ comment dòng (#), string có dấu ngoặc kép.
- Cross-platform: Chạy như nhau trên Windows (PowerShell/CMD), macOS (zsh/bash), Linux — không cần Cygwin hay WSL.
- Hỗ trợ tham số: Task nhận argument, có default value, validation.
- Variable interpolation: Biến môi trường, biến nội bộ, biến từ file .env.
- Shell completion: Tự động sinh completion cho bash, zsh, fish, PowerShell.
- Dry-run mode:
just --dry-runxem lệnh sẽ chạy mà không thực thi. - Watch mode:
just --watchtự động chạy lại khi file thay đổi.

Cài đặt Justfile
# macOS
brew install just
# Linux (Debian/Ubuntu)
sudo apt install just
# hoặc từ binary release
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
# Windows
scoop install just
# hoặc winget
winget install --id Casey.Just
# Rust (nếu có cargo)
cargo install just
Justfile cơ bản
Tạo file justfile (hoặc Justfile) ở root dự án:
# Biến toàn cục
version := "1.0.0"
build_dir := "target/release"
# Task mặc định (chạy khi gõ `just`)
default: build
# Task đơn giản
build:
cargo build --release
test:
cargo test
clean:
rm -rf target
# Task với tham số
deploy env="staging":
echo "Deploying {{version}} to {{env}}..."
./scripts/deploy.sh {{env}}
# Task phụ thuộc
release: test build
echo "Release {{version}} ready!"
# Variable từ môi trường
docker_build:
docker build -t myapp:{{version}} .
Tính năng nâng cao
1. Tham số (Parameters)
Task có thể nhận tham số vị trí hoặc named parameter:
# Tham số vị trí
greet name:
echo "Xin chào {{name}}!"
# Tham số có default
build profile="release":
cargo build --profile {{profile}}
# Tham số biến thể (variadic)
test *args:
cargo test {{args}}
# Validation
lint fix=false:
if fix == "true"
cargo clippy --fix
else
cargo clippy
Chạy: just greet "Chu Húng", just build profile=debug, just test -- --nocapture
2. Biến và interpolation
# Biến cục bộ
name := "my-project"
version := "1.0.0"
# Biến từ file .env (tự động load nếu có .env)
# .env nội dung: DATABASE_URL=postgres://localhost:5432/mydb
# Just tự động load các biến này
# Biến từ lệnh shell
git_hash := `git rev-parse --short HEAD`
git_branch := `git branch --show-current`
# Sử dụng
build:
echo "Building {{name}} v{{version}} ({{git_hash}} on {{git_branch}})"
# String interpolation trong lệnh
tag_image:
docker tag myapp:{{version}} myregistry/{{name}}:{{version}}
3. Điều kiện (Conditionals)
deploy env:
if env == "prod"
echo "Deploying to PRODUCTION - are you sure?"
read -p "Type 'yes' to confirm: " confirm
if confirm != "yes"
echo "Cancelled"
exit 1
else
echo "Deploying to {{env}}..."
./scripts/deploy.sh {{env}}
# Shorthand condition
test coverage=false:
if coverage == "true"
cargo test -- --coverage
else
cargo test
4. Private tasks và groups
# Private task (không hiện trong `just --list`, không chạy trực tiếp)
_install-deps:
cargo install cargo-watch cargo-expand
# Group: chạy nhiều task cùng lúc
lint: _fmt _clippy _check
_fmt:
cargo fmt --check
_clippy:
cargo clippy -- -D warnings
_check:
cargo check
# Alias
_ := _install-deps
setup: _install-deps
echo "Development environment ready!"
5. Shell completion
# Tự động sinh completion
just --completions bash > ~/.bash_completion.d/just
just --completions zsh > ~/.zsh/completions/_just
just --completions fish > ~/.config/fish/completions/just.fish
just --completions powershell > just.ps1
# Sau đó reload shell
Ví dụ thực tế: Dự án Rust web service
# justfile cho dự án Rust web service (axum + sqlx)
version := "0.1.0"
docker_image := "myorg/my-service"
registry := "ghcr.io"
# Default task
default: help
# Help custom
help:
@just --list
# Development
dev:
cargo watch -x run
# Database
db-up:
docker compose up -d postgres
db-down:
docker compose down
db-migrate:
sqlx migrate run
db-reset: db-down db-up db-migrate
# Testing
test:
cargo test
test-integration:
cargo test --test integration
# Linting
fmt:
cargo fmt
clippy:
cargo clippy -- -D warnings
lint: fmt clippy
# Build
build:
cargo build --release
build-docker:
docker build -t {{docker_image}}:{{version}} .
docker tag {{docker_image}}:{{version}} {{registry}}/{{docker_image}}:{{version}}
# Release
release: lint test build build-docker
docker push {{registry}}/{{docker_image}}:{{version}}
echo "Released {{version}} to {{registry}}"
# Deploy
deploy env:
kubectl set image deployment/{{name}} {{name}}={{registry}}/{{docker_image}}:{{version}} -n {{env}}
# Clean
clean:
cargo clean
docker rmi {{docker_image}}:{{version}} || true
So sánh với các công cụ khác
| Tính năng | Makefile | npm scripts | Justfile |
|---|---|---|---|
| Cross-platform | Không (chỉ Unix) | Có (Node.js required) | Có (binary đơn lẻ) |
| Cú pháp | Tab-based, cryptic | JSON string, escaping | Modern, readable |
| Tham số task | Khó (biến môi trường) | Khó (– truyền vào script) | Native, validation |
| Biến | Gán đơn giản | package.json + env | Mạnh mẽ, shell command |
| Shell completion | Không | Không | Có (bash/zsh/fish/pwsh) |
| Watch mode | Không | Cần nodemon/chokidar | Có (–watch) |
| Dry-run | Không | Không | Có (–dry-run) |
| Dependencies | Chỉ file timestamp | Không có | Task dependencies |
Best practices
- Đặt task mặc định là help:
default: helphoặc custom help task. - Dùng prefix
_cho private task: Task nội bộ không muốn expose ra ngoài. - Load .env file: Just tự động load .env — hữu ích cho secrets.
- Tách config và logic: Biến ở đầu file, task ở dưới.
- Dùng
@để ẩn lệnh:@echo "Done"chỉ hiển thị output, không hiển thị lệnh. - Group task liên quan:
lint: fmt clippy checkchạy toàn bộ lint pipeline. - Commit justfile vào repo: Toàn team dùng chung một task runner.
Kết luận
Justfile mang lại sự cân bằng giữa đơn giản của Makefile và tính năng của task runner hiện đại. Với binary ~3MB, zero dependency, cross-platform thực sự và cú pháp thân thiện, Justfile xứng đáng trở thành task runner mặc định cho mọi dự án — từ side project cá nhân đến production system quy mô lớn. Nếu bạn đang dùng Makefile, npm scripts, hoặc tập hợp các bash script rời rạc, hãy thử chuyển sang Justfile trong 15 phút — bạn sẽ thấy sự khác biệt ngay lập tức.
Just GitHub Repository, Just Manual, Just Cookbook (Ví dụ thực tế)
