Loading...
Loading...
Create or improve Makefiles with minimal complexity. Templates available: base, python-uv, python-fastapi, nodejs, go, chrome-extension, flutter.
npx skill4agent add olshansk/agent-skills makefileuv runuv run| Project Type | Template | Complexity |
|---|---|---|
| Any project | | Minimal |
| Python with uv | | Standard |
| Python FastAPI | | Full-featured |
| Node.js | | Standard |
| Go | | Standard |
| Chrome Extension | | Modular |
| Flutter App | | Modular |
Makefile # Main file with help + includes
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE mode, guards
build.mk # Build zip, version bump, releases
dev.mk # Test, lint, clean, installtemplates/chrome-extension-modules/makefiles/build-releasebuild-betaghdev-testdev-test-e2eVERBOSE=1 make <target>Makefile # Main file with help + includes
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE mode, guards
dev.mk # Setup, run simulator/device, devices, clean
build.mk # iOS/Android builds (IPA, APK, AAB)
deploy.mk # TestFlight upload
lint.mk # Dart analyze & formattemplates/flutter-modules/makefiles/flutter-run-iosflutter-run-androidflutter-run-deviceFLUTTER_IOS_DEVICEFLUTTER_ANDROID_DEVICEflutter-build-ipaflutter-deploy-testflightflutter-lint FIX=trueVERBOSE=1 make <target># Good - consistent prefixes (hyphens, not underscores)
build-release, build-zip, build-clean # Build tasks
dev-run, dev-test, dev-lint # Development tasks
db-start, db-stop, db-migrate # Database tasks
env-local, env-prod, env-show # Environment tasks
# Internal targets - prefix with underscore to hide from help
_build-zip-internal, _prompt-version # Not shown in make help
# Bad - inconsistent
run-dev, build, localEnv, test_net
build_release, dev_test # Underscores - don't use# Good - describes what it does
remove-bg # Removes background from image
format-code # Formats code
lint-check # Runs linting
# Bad - names the tool
rembg # What does this do?
prettier # Is this running prettier or configuring it?
eslint # UnclearGITHUB_REPO ?= owner/repo
OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
ARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
.PHONY: install-cli
install-cli: ## Download and install CLI from latest GitHub release
@RELEASE=$$(curl -fsSL https://api.github.com/repos/$(GITHUB_REPO)/releases/latest | grep tag_name | cut -d'"' -f4); \
echo "Installing $$RELEASE for $(OS)/$(ARCH)..."; \
curl -fsSL -o ~/.local/bin/cli \
"https://github.com/$(GITHUB_REPO)/releases/download/$$RELEASE/cli-$(OS)-$(ARCH)"; \
chmod +x ~/.local/bin/cli~/.local/binuv run# Good - uses uv run with ruff (modern tooling)
dev-check:
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
uv run mypy src/
dev-format:
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
# Bad - relies on manual venv activation
dev-format:
ruff format .uv syncenv-install:
uv sync # Uses pyproject.toml + lock filehelp:
@printf "$(BOLD)=== 🚀 API ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "api-run" "Start server"
@printf "%-25s $(GREEN)make api-run [--reload]$(RESET)\n" ""?=HELP_PATTERNSinclude ./makefiles/*.mkhelp:help-unclassified:%:_check-docker:
@docker info >/dev/null 2>&1 || { echo "Docker not running"; exit 1; }
db-start: _check-docker # Runs check first
docker compose up -dmake install-foo_### Internal check - hidden from help (no ##)
_check-rembg:
@command -v rembg >/dev/null 2>&1 || { \
printf "$(RED)$(CROSS) rembg not installed$(RESET)\n"; \
printf "$(YELLOW)Run: uv tool install \"rembg[cli]\"$(RESET)\n"; \
exit 1; \
}
# Public target - uses check as dependency
.PHONY: remove-bg
remove-bg: _check-rembg ## Remove background from image
rembg i "$(IN)" "$(OUT)"remove-bgrembgmake remove-bg.env# At top of Makefile, after .DEFAULT_GOAL
-include .env
.EXPORT_ALL_VARIABLES:# Allow: E2E_ENV=.test.env make test-e2e
test-e2e:
@set -a && . "$${E2E_ENV:-.env}" && set +a && uv run pytest tests/e2e/FIXFIX ?= false
dev-check: ## Run linting and type checks (FIX=false: check only)
$(call print_section,Running checks)
ifeq ($(FIX),true)
uv run ruff check --fix src/ tests/
uv run ruff format src/ tests/
else
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
endif
uv run mypy src/
$(call print_success,All checks passed)@printf "$(CYAN)%-25s$(RESET) %s\n" "dev-check" "Run linting (FIX=false: check only)"
@printf "%-25s $(GREEN)make dev-check FIX=true$(RESET) <- auto-fix issues\n" ""Makefile # Config, imports, help, catch-all
makefiles/
colors.mk # ANSI colors & print helpers
common.mk # Shell flags, VERBOSE, guards
<domain>.mk # Actual targets (build.mk, dev.mk, etc.)rg "make old-name"############################
### Legacy Target Aliases ##
############################
.PHONY: old-name
old-name: new_name ## (Legacy) Descriptionrg "make old-target"make helpmake -n targetmake helpCLAUDE.md##make helpmake help-unclassifiedhelp:
@printf "\n"
@printf "$(BOLD)$(CYAN)╔═══════════════════════════╗$(RESET)\n"
@printf "$(BOLD)$(CYAN)║ Project Name ║$(RESET)\n"
@printf "$(BOLD)$(CYAN)╚═══════════════════════════╝$(RESET)\n\n" @printf "$(BOLD)=== 🏗️ Build ===$(RESET)\n"
@grep -h -E '^build-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...
@printf "$(BOLD)=== 🔧 Development ===$(RESET)\n"
@grep -h -E '^dev-[a-zA-Z_-]+:.*?## .*$$' ... | awk ...helphelp-unclassifiedhelp-all__build-internal## (Legacy)make help @printf "$(BOLD)=== ❓ Help ===$(RESET)\n"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help" "Show this help"
@printf "$(CYAN)%-25s$(RESET) %s\n" "help-unclassified" "Show targets not in categorized help"
@printf "\n"sedhelp-unclassified: ## Show targets not in categorized help
@printf "$(BOLD)Targets not in main help:$(RESET)\n"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
sed 's/^[^:]*://' | \
grep -v -E '^(env-|dev-|clean|help)' | \
awk 'BEGIN {FS = ":.*?## "}; {printf "$(CYAN)%-25s$(RESET) %s\n", $$1, $$2}' || \
printf " (none)\n"# Good - concise description + example on next line
@printf "$(CYAN)%-14s$(RESET) %s\n" "scrape" "Fetch posts into SQLite, detect problems"
@printf " $(GREEN)make scrape SUBREDDITS=python,django LIMIT=10$(RESET)\n"
@printf "$(CYAN)%-14s$(RESET) %s\n" "dev-check" "Run ruff linter and formatter"
@printf " $(GREEN)make dev-check FIX=true$(RESET)\n"
# Bad - too verbose, multi-line explanation
@printf " $(CYAN)$(BOLD)setup$(RESET)\n"
@printf " Install Python dependencies using uv. Run this once after cloning.\n"
@printf " Creates .venv/ and installs packages from pyproject.toml.\n"
@printf " $(GREEN)make setup$(RESET)\n"$(GREEN)%:
@printf "$(RED)Unknown target '$@'$(RESET)\n"
@$(MAKE) help| Issue | Fix |
|---|---|
| Use |
Catch-all | Redirect to |
| Config vars scattered | Put all |
| Must match grep patterns in help target exactly |
| Duplicate defs in modules | Define once in root, reference in modules |
| Trailing whitespace in vars | Causes path splitting bugs - trim all variable definitions |
| Only use |
| Too many public targets | Don't expose |
| Appears grey/unreadable - use |
| Target named after tool | Name after the action: |
| Use |
No | Add |
make help # See categorized targets
make help-unclassified # Find orphaned targets
cat Makefile # Read structure
ls makefiles/*.mk 2>/dev/null # Check if modular
rg "make " --type md # Find external dependencies
grep -E '\s+$' Makefile makefiles/*.mk # Trailing whitespaceold_namenew-namehelp-unclassifiedmakefiles/_##$(YELLOW)make foo$(RESET).PHONYhelp-unclassified%:make help # Clean output?
make help-unclassified # Should be empty or minimal
make -n <target> # Dry-run key targetsreference.mdtemplates/modules/.PHONY: test
test: ## Run tests
$(call print_section,Running tests)
uv run pytest tests/ -v
$(call print_success,Tests passed).PHONY: db-start db-stop db-migrate
db-start: _check-docker ## Start database
docker compose up -d postgres
db-stop: ## Stop database
docker compose down
db-migrate: _check-postgres ## Run migrations
uv run alembic upgrade head