
Justfile Expert
- 137 installs
- 49 repo stars
- Updated August 4, 2026
- laurigates/claude-plugins
Author and maintain Justfiles that wrap build, test, lint, and deploy commands so local and CI tasks stay consistent and discoverable.
About
Provides Justfile expertise for defining dependable developer recipes: naming tasks, chaining dependencies, passing arguments, mirroring CI locally, and keeping automation readable so teams run the same build, test, and deploy flows from one command runner.
- Recipe design and dependencies
- Cross-platform command patterns
- Parameterized tasks
- CI-friendly targets
- Readable maintainer docs in recipes
Justfile Expert by the numbers
- 137 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #680 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/laurigates/claude-plugins --skill justfile-expertAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 137 |
|---|---|
| repo stars | ★ 49 |
| Last updated | August 4, 2026 |
| Repository | laurigates/claude-plugins ↗ |
What it does
Author and maintain Justfiles that wrap build, test, lint, and deploy commands so local and CI tasks stay consistent and discoverable.
Files
Justfile Expert
Expert knowledge for Just command runner, recipe development, and task automation with focus on cross-platform compatibility and project standardization.
When to Use This Skill
| Use this skill when... | Use alternative when... |
|---|---|
| Creating/editing justfiles for task automation | Need build system with incremental compilation → Make |
| Writing cross-platform project commands | Need tool version management bundled → mise tasks |
| Adding shebang recipes (Python, Node, Ruby, etc.) | Already using mise for all project tooling |
| Configuring dotenv loading and settings | Simple one-off shell scripts → Bash directly |
| Setting up CI/CD with just recipes | Project already has extensive Makefile |
| Standardizing recipes across projects | Need Docker-specific workflows → docker-compose |
Core Expertise
Command Runner Mastery
- Justfile syntax and recipe structure
- Cross-platform task automation (Linux, macOS, Windows)
- Parameter handling and argument forwarding
- Module organization for large projects
Recipe Development Excellence
- Recipe patterns for common operations
- Dependency management between recipes
- Shebang recipes for complex logic
- Environment variable integration
Project Standardization
- Golden template with standard naming and section structure
- Self-documenting project operations
- Portable patterns across projects
- Integration with CI/CD pipelines
Recipe Naming Conventions
| Rule | Pattern | Examples |
|---|---|---|
| Hyphen-separated | word-word | test-unit, format-check |
| Verb-first (actions) | verb-object | lint, build, clean |
| Noun-first (categories) | noun-verb | db-migrate, docs-serve |
| Private prefix | _name | _generate-secrets, _setup |
-check suffix | Read-only verification | format-check |
-fix suffix | Auto-correction | lint-fix, check-fix |
-watch suffix | Watch mode | test-watch, docs-watch |
| Modifiers after base | base-modifier | build-release (not release-build) |
Semantic Workflow Recipes
Standard composite recipes with defined meanings:
| Recipe | Composition | Purpose |
|---|---|---|
check | format-check + lint + typecheck | Code quality only, no tests |
pre-commit | format-check + lint + typecheck + test-unit | Fast, non-mutating validation |
ci | check + test-coverage + build | Full CI simulation |
clean | Remove build artifacts | Partial cleanup |
clean-all | clean + remove deps/caches | Full cleanup |
# Composite: code quality only (no tests)
check: format-check lint typecheck
# Pre-commit checks (fast, non-mutating)
pre-commit: format-check lint typecheck test-unit
@echo "Pre-commit checks passed"
# Full CI simulation
ci: check test-coverage build
@echo "CI simulation passed"
# Clean build artifacts
clean:
rm -rf dist build .next
# Clean everything including deps
clean-all: clean
rm -rf node_modules .venv __pycache__Key Capabilities
Recipe Parameters
- Required parameters:
recipe param:- must be provided - Default values:
recipe param="default":- optional with fallback - Variadic `+`:
recipe +FILES:- one or more arguments - *Variadic `
**:recipe *FLAGS:` - zero or more arguments - Environment export:
recipe $VAR:- parameter as env var
Settings Configuration
- `set dotenv-load`: Load
.envfile automatically - `set positional-arguments`: Enable
$1,$2syntax - `set export`: Export all variables as env vars
- `set shell`: Custom shell interpreter
- `set quiet`: Suppress command echoing
Recipe Attributes
- `[private]`: Hide from
--listoutput - `[no-cd]`: Don't change directory
- `[no-exit-message]`: Suppress exit messages
- `[unix]` / `[windows]` / `[linux]` / `[macos]`: Platform-specific recipes
- `[positional-arguments]`: Per-recipe positional args
- `[confirm]` / `[confirm("message")]`: Require confirmation before running
- `[group: "name"]`: Group recipes in
--listoutput - `[working-directory: "path"]`: Run in specific directory
Module System
- `mod name`: Declare submodule
- `mod name 'path'`: Custom module path
- Invocation:
just module::recipeorjust module recipe
Essential Syntax
Basic Recipe Structure
# Comment describes the recipe
recipe-name:
command1
command2Recipe with Parameters
build target:
@echo "Building {{target}}..."
cd {{target}} && make
test *args:
uv run pytest {{args}}Recipe Dependencies
default: build test
build: _setup
cargo build --release
_setup:
@echo "Setting up..."Variables and Interpolation
version := "1.0.0"
project := env('PROJECT_NAME', 'default')
info:
@echo "Project: {{project}} v{{version}}"Conditional Recipes
[unix]
open:
xdg-open http://localhost:8080
[windows]
open:
start http://localhost:8080Standard Recipes
Every project should provide these standard recipes, organized by section:
# Justfile - Project task runner
# Run `just` or `just help` to see available recipes
set dotenv-load
set positional-arguments
# Default recipe - show help
default:
@just --list
# Show available recipes with descriptions
help:
@just --list --unsorted
####################
# Development
####################
# Start development environment
dev:
# bun run dev / uv run uvicorn app:app --reload / skaffold dev
# Build for production
build:
# bun run build / cargo build --release / docker build
# Clean build artifacts
clean:
# rm -rf dist build .next
####################
# Code Quality
####################
# Run linter (read-only)
lint *args:
# bun run lint / uv run ruff check {{args}}
# Auto-fix lint issues
lint-fix:
# bun run lint:fix / uv run ruff check --fix .
# Format code (mutating)
format *args:
# bun run format / uv run ruff format {{args}}
# Check formatting without modifying (non-mutating)
format-check *args:
# bun run format:check / uv run ruff format --check {{args}}
# Type checking
typecheck:
# bunx tsc --noEmit / uv run basedpyright
####################
# Testing
####################
# Run all tests
test *args:
# bun test {{args}} / uv run pytest {{args}}
# Run unit tests only
test-unit *args:
# bun test --grep unit {{args}} / uv run pytest -m unit {{args}}
####################
# Workflows
####################
# Composite: code quality (no tests)
check: format-check lint typecheck
# Pre-commit checks (fast, non-mutating)
pre-commit: format-check lint typecheck test-unit
@echo "Pre-commit checks passed"
# Full CI simulation
ci: check test-coverage build
@echo "CI simulation passed"Section Structure
Organize recipes into these standard sections:
| Section | Recipes | Purpose |
|---|---|---|
| Metadata | default, help | Discovery and navigation |
| Development | dev, build, clean, start, stop | Core dev cycle |
| Code Quality | lint, lint-fix, format, format-check, typecheck | Code standards |
| Testing | test, test-unit, test-integration, test-e2e, test-watch | Test tiers |
| Workflows | check, pre-commit, ci | Composite operations |
| Dependencies | install, update | Package management |
| Database | db-migrate, db-seed, db-reset | Data operations |
| Kubernetes | skaffold, dev-k8s | Container orchestration |
| Documentation | docs, docs-serve | Project docs |
Use #################### comment blocks as section dividers for readability.
Common Patterns
Setup/Bootstrap Recipe
# Initial project setup
setup:
#!/usr/bin/env bash
set -euo pipefail
echo "Installing dependencies..."
uv sync
echo "Setting up pre-commit..."
pre-commit install
echo "Done!"Docker Integration
# Build container image
docker-build tag="latest":
docker build -t {{project}}:{{tag}} .
# Run container
docker-run tag="latest" *args:
docker run --rm -it {{project}}:{{tag}} {{args}}
# Push to registry
docker-push tag="latest":
docker push {{registry}}/{{project}}:{{tag}}Database Operations
# Run database migrations
db-migrate:
uv run alembic upgrade head
# Create new migration
db-revision message:
uv run alembic revision --autogenerate -m "{{message}}"
# Reset database
db-reset:
uv run alembic downgrade base
uv run alembic upgrade headCI/CD Recipes
# Full CI check (lint + test + build)
ci: lint test build
@echo "CI passed!"
# Release workflow
release version:
git tag -a "v{{version}}" -m "Release {{version}}"
git push origin "v{{version}}"MCP Integration (just-mcp)
The just-mcp MCP server enables AI assistants to discover and execute justfile recipes through the Model Context Protocol, reducing context waste since the AI doesn't need to read the full justfile.
Installation:
# Via npm
npx just-mcp --stdio
# Via pip/uvx
uvx just-mcp --stdio
# Via cargo
cargo install just-mcpClaude Desktop configuration (`.claude/mcp.json`):
{
"mcpServers": {
"just-mcp": {
"command": "npx",
"args": ["-y", "just-mcp", "--stdio"]
}
}
}Available MCP Tools:
list_recipes- Discover all recipes and parametersrun_recipe- Execute a recipe with argumentsget_recipe_info- Get detailed recipe documentationvalidate_justfile- Check for syntax errors
Agentic Optimizations
| Context | Command |
|---|---|
| List all recipes | just --list or just -l |
| Dry run (preview) | just --dry-run recipe |
| Show variables | just --evaluate |
| JSON recipe list | just --dump --dump-format json |
| Verbose execution | just --verbose recipe |
| Specific justfile | just --justfile path recipe |
| Working directory | just --working-directory path recipe |
| Choose interactively | just --choose |
Best Practices
Recipe Development Workflow 1. Name clearly: Use descriptive, verb-based names (build, test, deploy) 2. Document always: Add comment before each recipe 3. Use defaults: Provide sensible default parameter values 4. Group logically: Organize with section comments 5. Hide internals: Mark helper recipes as [private] 6. Test portability: Verify on all target platforms
Critical Guidelines
- Always provide
defaultrecipe pointing to help - Use
@prefix to suppress command echo when appropriate - Use shebang recipes for multi-line logic
- Prefer
set dotenv-loadfor configuration - Use modules for large projects (>20 recipes)
- Include variadic
*argsfor passthrough flexibility - Quote all variables in shell commands
Comparison with Alternatives
| Feature | Just | Make | mise tasks |
|---|---|---|---|
| Syntax | Simple, clear | Complex, tabs required | YAML |
| Dependencies | Built-in | Built-in | Manual |
| Parameters | Full support | Limited | Full support |
| Cross-platform | Excellent | Good | Excellent |
| Tool versions | No | No | Yes |
| Error messages | Clear | Cryptic | Clear |
| Installation | Single binary | Pre-installed | Requires mise |
When to use Just:
- Cross-project standard recipes
- Simple, readable task automation
- No tool version management needed
When to use mise tasks:
- Project-specific with tool version pinning
- Already using mise for tool management
When to use Make:
- Legacy projects with existing Makefiles
- Build systems requiring incremental compilation
For the golden justfile template, detailed syntax reference, advanced patterns, and troubleshooting, see REFERENCE.md.
Justfile Expert - Detailed Reference
Golden Justfile Template
Use this template as a starting point for new projects. Uncomment and adapt recipes for your technology stack.
# Justfile - Project task runner
# Run `just` or `just help` to see available recipes
# https://just.systems/
####################
# Settings
####################
# set dotenv-load # Uncomment if using .env files
# set positional-arguments # Uncomment if recipes use $1, $2, etc.
####################
# Variables
####################
# PROJECT := "my-project"
# NAMESPACE := "my-namespace"
####################
# Metadata
####################
# Default recipe - show help
default:
@just --list
# Show available recipes with descriptions
help:
@just --list --unsorted
####################
# Development
####################
# Start development environment
dev:
echo "TODO: Start dev server"
# bun run dev
# uv run python manage.py runserver
# docker-compose up
# skaffold dev --port-forward
# Build for production
build:
echo "TODO: Build project"
# bun run build
# skaffold build
# docker-compose build
# Clean build artifacts
clean:
echo "TODO: Clean artifacts"
# rm -rf dist build .next node_modules/.cache
# find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
####################
# Code Quality
####################
# Run linter (read-only)
lint *args:
echo "TODO: Run linter"
# bun run lint {{ args }}
# uv run ruff check {{ args }}
# Auto-fix lint issues
# lint-fix:
# bun run lint:fix
# uv run ruff check --fix .
# Format code (mutating)
format *args:
echo "TODO: Format code"
# bun run format {{ args }}
# uv run ruff format {{ args }}
# Check code formatting without modifying (non-mutating)
format-check *args:
echo "TODO: Check formatting"
# bun run format:check {{ args }}
# uv run ruff format --check {{ args }}
# TypeScript/Python type checking
# typecheck:
# bunx tsc --noEmit --skipLibCheck
# uv run basedpyright
# Composite: format-check + lint + typecheck (code quality only, no tests)
# check: format-check lint typecheck
# Check and auto-fix
# check-fix:
# bun run check:fix
####################
# Testing
####################
# Run all tests
test *args:
echo "TODO: Run tests"
# bun test {{ args }}
# uv run pytest -v {{ args }}
# Run unit tests only
# test-unit *args:
# bun run test:unit {{ args }}
# uv run pytest -m unit -v {{ args }}
# Run integration tests
# test-integration *args:
# bun run test:integration {{ args }}
# uv run pytest -m integration -v {{ args }}
# Run tests with coverage report
# test-coverage:
# bun run test:coverage
# uv run pytest --cov --cov-report=html --cov-report=term-missing
####################
# Workflows
####################
# Pre-commit checks (fast, non-mutating)
pre-commit: format-check lint test
@echo "Pre-commit checks passed"
# With typecheck: pre-commit: format-check lint typecheck test-unit
# Full CI simulation
ci: format-check lint test build
@echo "CI simulation passed"
# With typecheck + coverage: ci: check test-coverage build
####################
# Dependencies
####################
# Install dependencies
# install:
# bun install --frozen-lockfile
# uv sync
# Update all dependencies
# update:
# bun update
# uv lock --upgrade
####################
# Database
####################
# Run database migrations
# db-migrate:
# uv run python manage.py migrate
# bun run db:migrate
# Seed database with test data
# db-seed:
# bun run db:seed
# Reset database (WARNING: destroys data)
# db-reset:
# echo "WARNING: This will delete all database data"
####################
# Kubernetes
####################
# Start Skaffold development
# skaffold:
# skaffold dev --port-forward
# Start Skaffold with file sync (hot reload)
# dev-k8s:
# skaffold dev -p dev --port-forward
####################
# Documentation
####################
# Generate documentation
# docs:
# bun run docs
# Serve documentation locally
# docs-serve:
# bun run docs:serveNaming Rules Summary
- Hyphen-separated:
test-unit,format-check,db-migrate - Verb-first for actions:
lint,format,build,test,clean - Noun-first for categories:
db-migrate,db-seed,docs-serve - `_` prefix for private:
_generate-secrets,_setup - Modifiers after base:
lint-fix(notfix-lint),build-release(notrelease-build) - `-check` suffix: Read-only verification (
format-check) - `-fix` suffix: Auto-correction (
lint-fix,check-fix) - `-watch` suffix: Watch mode (
test-watch,docs-watch)
Semantic Definitions
| Recipe | Equals | Description |
|---|---|---|
check | format-check + lint + typecheck | Code quality only, no tests |
pre-commit | format-check + lint + typecheck + test-unit | Non-mutating, fast |
ci | check + test-coverage + build | Full CI simulation |
clean | Remove build artifacts | Partial cleanup |
clean-all | clean + remove deps/caches | Full cleanup |
Complete Syntax Reference
Settings
# Load .env file automatically
set dotenv-load
# Load specific .env filename (searches in working dir and parents)
set dotenv-filename := ".env.local"
# Load .env from specific path (absolute or relative to working dir)
# Takes precedence over dotenv-filename; can override with -E flag
set dotenv-path := "config/.env"
# Override existing env vars with .env values (default: false)
set dotenv-override
# Required .env file (fail if missing, default: false)
set dotenv-required
# Export all variables as environment variables
set export
# Enable $1, $2 positional argument syntax
set positional-arguments
# Suppress command echoing globally
set quiet
# Set custom shell
set shell := ["bash", "-euo", "pipefail", "-c"]
# Windows-specific shell
set windows-shell := ["powershell.exe", "-NoLogo", "-Command"]
# Allow duplicate recipe names (last wins)
set allow-duplicate-recipes
# Allow duplicate variables (last wins)
set allow-duplicate-variables
# Fail on first error in recipe
set fallback
# Use working directory for imports
set working-directory := "subdir"Attributes
# Hide recipe from --list
[private]
_helper:
echo "Internal use only"
# Don't change to justfile directory
[no-cd]
anywhere:
pwd
# Suppress exit code message
[no-exit-message]
may-fail:
exit 1
# Unix-only recipe
[unix]
open:
xdg-open .
# Windows-only recipe
[windows]
open:
start .
# macOS-only recipe
[macos]
open:
open .
# Linux-only recipe
[linux]
open:
xdg-open .
# Enable positional arguments for this recipe
[positional-arguments]
run:
echo $1 $2
# Confirm before running
[confirm]
dangerous:
rm -rf ./data
# Custom confirmation message
[confirm("Are you sure you want to deploy?")]
deploy:
./deploy.sh
# Run in specific directory
[working-directory: "frontend"]
build-ui:
npm run build
# Group recipes in --list output
[group: "database"]
db-migrate:
alembic upgrade headBuilt-in Functions
# Architecture detection
arch := arch() # "x86_64", "aarch64", etc.
# OS detection
os := os() # "linux", "macos", "windows"
os_family := os_family() # "unix", "windows"
# Environment variables
home := env('HOME') # Get or fail
port := env('PORT', '8080') # Get with default
# Path operations
parent := parent_directory('a/b') # "a"
stem := file_stem('foo.txt') # "foo"
name := file_name('a/b/foo.txt') # "foo.txt"
ext := extension('foo.tar.gz') # "gz"
base := without_extension('f.txt') # "f"
# Directory functions
home_dir := home_directory() # User's home
cache := cache_directory() # Cache dir
config := config_directory() # Config dir
data := data_directory() # Data dir
# String operations
upper := uppercase('hello') # "HELLO"
lower := lowercase('HELLO') # "hello"
trim := trim(' hi ') # "hi"
trim_start := trim_start(' hi ') # "hi "
trim_end := trim_end(' hi ') # " hi"
replace := replace('ab', 'a', 'x') # "xb"
replace_re := replace_regex('a1b2', '\d', 'X') # "aXbX"
# Case conversion
snake := snakecase('fooBar') # "foo_bar"
kebab := kebabcase('fooBar') # "foo-bar"
title := titlecase('hello world') # "Hello World"
# String building
prefixed := prepend('prefix_', 'name') # "prefix_name"
suffixed := append('name', '_suffix') # "name_suffix"
quoted := quote("it's") # "'it'\"'\"'s'" (shell-safe)
# Path joining
full := join('a', 'b', 'c') # "a/b/c"
clean := clean('a//b/../c') # "a/c"
# Conditionals
val := if os() == "linux" { "apt" } else { "brew" }
# UUID generation
id := uuid() # Random UUID
# SHA256 hash
hash := sha256('content')
hash_file := sha256_file('path')
# Blake3 hash (faster alternative)
b3_hash := blake3('content')
b3_file := blake3_file('path')
# Justfile location
just_dir := justfile_directory()
just_path := justfile()
# External command execution
output := shell('echo hello') # Execute and capture output
output := shell('echo', 'hello') # With separate args
# Executable discovery
bin_path := which('python3') # Find in PATH, empty if not found
required_bin := require('python3') # Find in PATH, error if missing
# File operations
exists := path_exists('config.json') # Boolean check
contents := read('VERSION') # Read file contents
# System info
cpus := num_cpus() # Number of CPUs
# Error handling
error('message') # Abort with error message
# Datetime
now := datetime('%Y-%m-%d') # Current date/time formatted
# Semantic version matching
matches := semver_matches('1.2.3', '>=1.0.0')
# Random selection
pick := choose('a', 'b', 'c') # Random item from listParameter Patterns
# Required parameter
build target:
cargo build --package {{target}}
# Parameter with default
test mode="debug":
cargo test --profile {{mode}}
# Multiple parameters
deploy env tag:
kubectl set image deployment/app app={{tag}} -n {{env}}
# Variadic + (one or more)
backup +files:
tar -czf backup.tar.gz {{files}}
# Variadic * (zero or more)
test *args:
cargo test {{args}}
# Default for variadic
lint *flags="-q":
ruff check {{flags}} .
# Export as environment variable
run $PORT="8080":
./server --port $PORT
# Positional arguments (with attribute)
[positional-arguments]
exec *args:
"$@"Advanced Patterns
Shebang Recipes
Recipes starting with #! execute as scripts, saved to a temp file and run with the specified interpreter.
Platform Behavior:
- Unix/macOS: OS handles shebang natively
- Windows: Just manually parses the shebang and invokes the interpreter (no native shebang support)
Using `-S` flag for arguments:
# When interpreter needs arguments, use -S to split them
process:
#!/usr/bin/env -S python3 -u
import sys
print("Unbuffered output", flush=True)
strict-bash:
#!/usr/bin/env -S bash -euo pipefail
echo "Running with strict mode"# Python script
analyze:
#!/usr/bin/env python3
import json
import sys
with open('data.json') as f:
data = json.load(f)
print(f"Found {len(data)} items")
# Bash with strict mode
setup:
#!/usr/bin/env bash
set -euo pipefail
echo "Installing dependencies..."
pip install -r requirements.txt
echo "Running migrations..."
python manage.py migrate
echo "Done!"
# Ruby script
generate:
#!/usr/bin/env ruby
require 'erb'
template = ERB.new(File.read('template.erb'))
puts template.result(binding)
# Node.js script
process:
#!/usr/bin/env node
const fs = require('fs');
const data = JSON.parse(fs.readFileSync('config.json'));
console.log(`Processing ${data.name}...`);Dependency Chains
# Simple dependency
deploy: build test
./deploy.sh
# Dependency with arguments
release version: (build version) (tag version)
echo "Released {{version}}"
build version:
cargo build --release
tag version:
git tag -a "v{{version}}" -m "Release {{version}}"
# Conditional dependency execution
ci:
just lint
just test
just buildRecipe Aliases
# Simple alias
alias t := test
alias b := build
# Alias to module recipe
mod backend
alias api := backend::serveDynamic Recipes
# Recipe selection based on OS
install-deps:
just _install-deps-{{os()}}
[private]
_install-deps-linux:
sudo apt install build-essential
[private]
_install-deps-macos:
brew install gcc
[private]
_install-deps-windows:
choco install mingwModule System
Basic Modules
# justfile
mod database
mod frontend 'ui/justfile'
# Invoke: just database::migrate
# Or: just database migrate# database.just (or database/mod.just)
migrate:
alembic upgrade head
seed:
python seed.pyModule Organization
project/
├── justfile # Main justfile
├── database.just # Database module
├── frontend/
│ └── mod.just # Frontend module
└── backend/
├── mod.just # Backend module
└── api.just # Nested submodule# justfile
mod database
mod frontend 'frontend/mod.just'
mod backend 'backend/mod.just'
# Default shows all modules
default:
@just --list
@echo ""
@echo "Modules: database, frontend, backend"Private Modules
# Module with private recipes
mod _internal # Hidden from --list
# Or mark recipes private within module
[private]
helper:
echo "Internal"Integration Examples
Docker Compose Integration
set dotenv-load
project := env('COMPOSE_PROJECT_NAME', 'myapp')
# Start all services
up *args:
docker compose up -d {{args}}
# Stop all services
down:
docker compose down
# View logs
logs *services:
docker compose logs -f {{services}}
# Execute command in container
exec service *cmd:
docker compose exec {{service}} {{cmd}}
# Rebuild and restart
rebuild service:
docker compose build {{service}}
docker compose up -d {{service}}
# Full reset
reset:
docker compose down -v
docker compose build
docker compose up -dGitHub Actions CI
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: extractions/setup-just@v2
- run: just ci# justfile
ci: lint test build
@echo "CI passed!"
lint:
ruff check .
ruff format --check .
test:
pytest --cov
build:
docker build -t app .Pre-commit Hook Integration
# .pre-commit-config.yaml
repos:
- repo: local
hooks:
- id: just-lint
name: Lint with just
entry: just lint
language: system
pass_filenames: falseIDE Configuration (VS Code)
// .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "just: test",
"type": "shell",
"command": "just test",
"group": "test",
"problemMatcher": []
},
{
"label": "just: build",
"type": "shell",
"command": "just build",
"group": "build",
"problemMatcher": []
}
]
}Language-Specific Templates
Python (uv)
set dotenv-load
# Run linters
lint:
uv run ruff check .
uv run ruff format --check .
# Format code
format:
uv run ruff format .
uv run ruff check --fix .
# Run tests
test *args:
uv run pytest {{args}}
# Run tests with coverage
test-cov:
uv run pytest --cov --cov-report=html
# Type checking
typecheck:
uv run pyright
# Build package
build:
uv build
# Development server
dev:
uv run uvicorn app:app --reload
# Clean artifacts
clean:
find . -type f -name "*.pyc" -delete
find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
rm -rf .pytest_cache .ruff_cache .coverage htmlcov dist build *.egg-infoNode.js (Bun)
set dotenv-load
# Run linters
lint:
bun run lint
# Format code
format:
bun run format
# Run tests
test *args:
bun test {{args}}
# Development server
dev:
bun run dev
# Build for production
build:
bun run build
# Clean artifacts
clean:
rm -rf node_modules dist .next .turbo .cache
# Install dependencies
install:
bun installRust
# Run linters
lint:
cargo clippy -- -D warnings
# Format code
format:
cargo fmt
# Run tests
test *args:
cargo nextest run {{args}}
# Build release
build:
cargo build --release
# Run with arguments
run *args:
cargo run -- {{args}}
# Clean artifacts
clean:
cargo clean
# Check without building
check:
cargo check
# Documentation
doc:
cargo doc --openGo
# Run linters
lint:
golangci-lint run
# Format code
format:
gofmt -s -w .
goimports -w .
# Run tests
test *args:
go test ./... {{args}}
# Build binary
build:
go build -o bin/app ./cmd/app
# Run application
run *args:
go run ./cmd/app {{args}}
# Clean artifacts
clean:
rm -rf bin dist
go clean -cache
# Update dependencies
deps:
go mod tidy
go mod downloadTroubleshooting
Common Errors and Solutions
"Recipe requires at least one argument"
# Wrong - missing argument
just test
# Fix - provide required argument or add default
test target="all":
pytest {{target}}"Unknown recipe"
# Check available recipes
just --list
# Check for typos in recipe name
just --list | grep "partial-name""No justfile found"
# Justfile must be named: justfile, Justfile, .justfile
# Or specify explicitly
just --justfile path/to/justfile recipe"Recipe line failed"
# Each line runs in separate shell
wrong:
cd subdir
pwd # Still in original directory!
# Fix - use single line or shebang
right:
cd subdir && pwd
right-alt:
#!/usr/bin/env bash
cd subdir
pwd"Variable not found"
# Wrong - undefined variable
foo:
echo {{undefined}}
# Fix - define or use default
var := env('VAR', 'default')
foo:
echo {{var}}Debugging Recipes
# Show recipe without running
just --dry-run recipe
# Show all variables
just --evaluate
# Show parsed justfile
just --dump
# Verbose execution
just --verbose recipe
# Show justfile search path
just --list --justfileCross-Platform Gotchas
# Problem: Different path separators
# Solution: Use / always (just handles it)
# Problem: Different line endings
# Solution: Add to .gitattributes
# justfile text eol=lf
# Problem: Different shells
# Solution: Explicit shell setting
set shell := ["bash", "-euo", "pipefail", "-c"]
# Or use shebang for complex recipes
complex:
#!/usr/bin/env bash
set -euo pipefail
# Script contentPerformance Tips
1. Use `@` prefix to suppress command echo (faster output) 2. Avoid unnecessary dependencies - only depend on what's needed 3. Use shebang recipes for multi-command operations (single process) 4. Cache expensive operations - use variables for repeated values 5. Parallelize independent work - run tasks concurrently with &
# Parallel execution
all: (build "frontend") (build "backend")
wait
build target:
cd {{target}} && npm run build &Quick Reference
| Command | Description |
|---|---|
just | Run default recipe |
just recipe | Run specific recipe |
just --list | List available recipes |
just --dry-run recipe | Show without running |
just --evaluate | Show all variables |
just --dump | Show parsed justfile |
just --choose | Interactive recipe selection |
just --completions bash | Generate shell completions |
just mod::recipe | Run recipe in module |