Taskfile for project automation
Task runner with built-in docs, descriptions, and YAML syntax.
Makefiles work. I’ve used them for years. But the DevEx is stuck in 1976.
Taskfile gives you the same automation with task descriptions, built-in help, and YAML instead of tab hell. It’s what Makefiles should have evolved into.
What Makefiles get wrong
Run make in most projects and you get an error or it builds something random. Run make help and nothing happens unless someone wrote a custom target with grep and awk.
Task descriptions? You write them in comments and hope someone reads the file. Dependencies between tasks? They work, but the syntax looks like line noise.
Makefiles are great for what they do. But discoverability is terrible.
Taskfile fixes the DevEx problems
Run task without arguments and you get a list of available tasks with descriptions. Run task --list and you see everything organized.
Each task has a description. You know what it does before running it.
version: '3'
tasks:
dev:
desc: Start development server
cmds:
- npm run dev
test:
desc: Run test suite
cmds:
- pytest tests/
deploy:
desc: Deploy to production
deps: [test, build]
cmds:
- ./scripts/deploy.sh No tabs to break. No special syntax to remember. Just YAML that does what you expect.
Use it as a project entrypoint
I organize projects with one Taskfile.yaml at the root and scripts in tasks/. Taskfile becomes the entrypoint, scripts do the actual work.
project/
├── Taskfile.yaml
├── tasks/
│ ├── setup.sh
│ ├── deploy.py
│ ├── backup.nu
│ └── check.sh
├── src/
└── tests/ Your Taskfile.yaml just calls the scripts:
version: '3'
tasks:
setup:
desc: Initialize development environment
cmds:
- bash tasks/setup.sh
deploy:
desc: Deploy application
cmds:
- python tasks/deploy.py {{.ENV}}
backup:
desc: Backup database
cmds:
- nu tasks/backup.nu
check:
desc: Run health checks
cmds:
- bash tasks/check.sh Scripts can be in any language. Bash for system stuff, Python for logic, Nushell for data processing. Taskfile doesn’t care. It just runs them.
Why this structure works
Scripts get complex. Taskfile keeps them organized and discoverable.
New developers run task and see what’s available. No hunting through bash scripts or reading README files.
You can test scripts independently. Run bash tasks/setup.sh directly if you need to debug. Taskfile is just the entrypoint.
Dependencies work like you’d expect:
tasks:
build:
desc: Build application
cmds:
- bash tasks/build.sh
test:
desc: Run tests
deps: [build]
cmds:
- bash tasks/test.sh
deploy:
desc: Deploy to production
deps: [test]
cmds:
- python tasks/deploy.py Run task deploy and it runs build, then test, then deploy. Clean and predictable.
Variables and templating
Pass variables to your tasks:
tasks:
deploy:
desc: Deploy to environment
cmds:
- python tasks/deploy.py --env={{.ENV}}
logs:
desc: Show logs for service
cmds:
- bash tasks/logs.sh {{.SERVICE}} Call it with task deploy ENV=prod or task logs SERVICE=api.
You can set default values:
tasks:
deploy:
desc: Deploy to environment
vars:
ENV: staging
cmds:
- python tasks/deploy.py --env={{.ENV}} Task-specific directories
Run tasks from specific directories:
tasks:
frontend:
desc: Start frontend dev server
dir: frontend/
cmds:
- npm run dev
backend:
desc: Start backend server
dir: backend/
cmds:
- go run main.go The task changes to that directory before running. Cleaner than cd in scripts.
Silent tasks and output control
Some tasks are noisy. Control the output:
tasks:
install:
desc: Install dependencies
cmds:
- npm install
silent: true
status:
desc: Check service status
cmds:
- task: check-db
- task: check-api
silent: true
check-db:
cmds:
- bash tasks/check-db.sh
check-api:
cmds:
- bash tasks/check-api.sh When to use Makefiles instead
If you’re building C, C++, or anything that needs real dependency tracking based on file timestamps, use Make. That’s what it’s built for.
Taskfile is for running commands, not tracking source file dependencies. It doesn’t know if a file changed. It just runs tasks.
For project automation, dev workflows, and deployment scripts, Taskfile wins on DevEx.
Getting started
Install it:
# macOS
brew install go-task
# Linux
sh -c '$(curl --location https://taskfile.dev/install.sh)' -- -d -b ~/.local/bin
# Or use your package manager Create a Taskfile.yaml:
version: '3'
tasks:
hello:
desc: Say hello
cmds:
- echo 'Hello from Taskfile' Run task hello. That’s it.
Start moving your scripts into tasks/ and reference them from Taskfile.yaml. Your project becomes instantly more discoverable.
Bottom line
You can do the same things with Make. Makefiles work great, they’re battle-tested, installed everywhere, and if you know the syntax, they’re fast to write.
Taskfile has built-in docs and YAML syntax. That’s it. Make is still great.
Reality is often more nuanced. But me? Nuance bores me. I'd rather be clear.