Taskfile: Modern Task Runner for Any Project
In this tutorial, you'll learn Taskfile including task dependencies, variables, templating, cross-platform support, and using Task as a modern alternative to Make for any programming language.
Why Taskfile Matters
Make is universal but its syntax is cryptic. Tabs vs spaces, legacy variable syntax, and platform-specific commands make Makefiles error-prone. Task brings a clean YAML syntax, native cross-platform support, task dependencies, and built-in templating. It is a single binary with no dependencies.
By the end of this guide, you will write Taskfiles for any project, use dependencies and variables, and replace Makefiles with cleaner Taskfile equivalents.
What is Task?
Task is a task runner and build tool written in Go. It reads a Taskfile.yml and executes tasks with dependencies, variables, and environment-specific configurations.
flowchart LR A[Taskfile.yml] --> B[Task: build] A --> C[Task: test] A --> D[Task: lint] B --> E[Dependencies] E --> F[Task: install-deps] B --> G[Commands] G --> H[cmds: [go build, npm run build]] C --> I[cmds: [go test, npm test]]
Installation
# macOS
brew install go-task
# Linux (script)
sh -c "$(curl -ssL https://taskfile.dev/install.sh)" -- -d
# Verify
task --version
# Task version: 3.38.0
Your First Taskfile
# Taskfile.yml
version: '3'
tasks:
hello:
cmds:
- echo "Hello, Task!"
silent: true
task hello
Expected Output
Hello, Task!
Tasks with Dependencies
version: '3'
tasks:
build:
cmds:
- go build -o app .
generate:
cmds:
- go generate ./...
install-deps:
cmds:
- go mod download
- npm install
test:
deps: [install-deps]
cmds:
- go test ./...
- npm test
all:
deps: [generate, build, test]
task test
# Runs install-deps first, then test
Variables
version: '3'
vars:
APP_NAME: myapp
BUILD_DIR: dist
GO_FLAGS: -ldflags="-s -w"
tasks:
build:
cmds:
- mkdir -p {{.BUILD_DIR}}
- go build {{.GO_FLAGS}} -o {{.BUILD_DIR}}/{{.APP_NAME}} .
env:
CGO_ENABLED: '0'
GOOS: linux
Task-Level Variables
version: '3'
tasks:
greet:
vars:
NAME: '{{default "World" .NAME}}'
cmds:
- echo "Hello, {{.NAME}}!"
# Usage: task greet NAME=Alice
# Output: Hello, Alice!
Dynamic Variables
version: '3'
tasks:
version:
cmds:
- echo "{{.DATE}}-{{.GIT_HASH}}"
vars:
DATE:
sh: date +%Y%m%d
GIT_HASH:
sh: git rev-parse --short HEAD
Cross-Platform Support
Task handles cross-platform quirks natively.
version: '3'
tasks:
install:
cmds:
- task: install-{{OS}}
install-linux:
cmds:
- sudo apt-get install -y libssl-dev
install-darwin:
cmds:
- brew install openssl
install-windows:
cmds:
- choco install openssl
Platform-Specific Commands
version: '3'
tasks:
clean:
cmds:
- |
{{if eq OS "windows"}}
del /f /q {{.BUILD_DIR}}\*
{{else}}
rm -rf {{.BUILD_DIR}}/*
{{end}}
Real-World Taskfiles
Go Project
version: '3'
vars:
APP: server
VERSION: '{{default "dev" .VERSION}}'
tasks:
default:
deps: [build]
install-deps:
cmds:
- go mod download
build:
deps: [install-deps]
cmds:
- go build -ldflags="-X main.version={{.VERSION}}" -o {{.APP}} .
test:
deps: [install-deps]
cmds:
- go test -v -race -cover ./...
lint:
cmds:
- golangci-lint run ./...
run:
deps: [build]
cmds:
- ./{{.APP}}
clean:
cmds:
- rm -f {{.APP}}
- rm -rf dist/
dev:
deps: [build]
cmds:
- ./{{.APP}}
sources:
- ./**/*.go
watch: true
Node.js Project
version: '3'
vars:
NODE_OPTIONS: '--max-old-space-size=4096'
tasks:
install:
cmds:
- npm ci
dev:
deps: [install]
cmds:
- npm run dev
build:
deps: [install]
cmds:
- npm run build
test:
deps: [install]
cmds:
- npm test
env:
CI: 'true'
lint:
deps: [install]
cmds:
- npm run lint
format:
cmds:
- npx prettier --write 'src/**/*.{js,ts,jsx,tsx}'
docker-build:
cmds:
- docker build -t myapp:{{.VERSION}} .
Python Project
version: '3'
vars:
VENV: .venv
PYTHON: '{{default "python3" .PYTHON}}'
tasks:
venv:
status:
- test -d {{.VENV}}
cmds:
- '{{.PYTHON}} -m venv {{.VENV}}'
install:
deps: [venv]
cmds:
- '{{.VENV}}/bin/pip install -r requirements.txt'
dev:
deps: [install]
cmds:
- '{{.VENV}}/bin/uvicorn app.main:app --reload'
test:
deps: [install]
cmds:
- '{{.VENV}}/bin/pytest -v tests/'
lint:
deps: [install]
cmds:
- '{{.VENV}}/bin/flake8 src/'
- '{{.VENV}}/bin/mypy src/'
clean:
cmds:
- rm -rf {{.VENV}}
- find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
Taskfile Includes
version: '3'
includes:
docker: ./docker/Taskfile.yml
deploy: ./deploy/Taskfile.yml
tasks:
build:
deps:
- docker:build
Using Go Templates
version: '3'
tasks:
greet:
cmds:
- |
echo "{{if .NAME}}Hello, {{.NAME}}!{{else}}Hello, World!{{end}}"
list:
cmds:
- |
{{range .ITEMS}}
echo "Item: {{.}}"
{{end}}
Comparison to Make
| Feature | Make | Task |
|---|---|---|
| Configuration syntax | Makefile (tab-based) | Taskfile.yml (YAML) |
| Cross-platform | Poor (shell-dependent) | Excellent (built-in OS detection) |
| Task dependencies | Yes (target-based) | Yes (deps array) |
| Variables | $(VAR) |
{{.VAR}} (Go templates) |
| Default task | First target | default task |
| Watch mode | No | Built-in (watch: true) |
| Silent commands | @ prefix |
silent: true |
Common Errors
| Problem | Cause | Fix |
|---|---|---|
yaml: unmarshal errors |
Invalid YAML syntax | Check indentation (2 spaces) and quotes |
task: No Taskfile.yml found |
Wrong directory | Ensure you are in the directory with the Taskfile |
undefined variable "VAR" |
Variable not defined | Use {{default "value" .VAR}} for optional vars |
command not found |
Tool not installed | Add an install-deps task or document prerequisites |
watch: need sources |
Watch mode requires sources list | Add sources: with glob patterns |
Practice Questions
1. What file does Task read for configuration?
Taskfile.yml.
2. How do you create a task dependency in Task?
Use the deps: field with a list of task names.
3. How do you access a variable in a Taskfile?
{{.VARIABLE_NAME}} using Go template syntax.
4. How do you make a task run silently (no command echo)?
Set silent: true in the task definition.
5. How does Task handle cross-platform differences?
It provides the built-in {{OS}} variable and supports conditional expressions.
Challenge
Create a Taskfile.yml for a multi-language project that uses Node.js for the frontend and Python for the backend. Include tasks for: installing dependencies for both, running both dev servers simultaneously, running all tests, building for production, and Docker image creation. Use cross-platform friendly commands.
Real-World Task
Replace an existing Makefile or npm scripts with a Taskfile in a project you work on. Include all the same functionality: build, test, lint, format, clean, and deploy. Add watch mode for development. Compare the experience and document the Migration steps.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro