Taskfile: A Modern Alternative to Make

Makefiles work. They have worked for decades. But they have sharp edges — tab sensitivity, implicit rules, .PHONY everywhere, and arcane syntax for anything beyond the basics.

Taskfile is a YAML-based task runner that does what most people actually use Make for, without the footguns.

Installation

brew install go-task

Basic Taskfile

version: '3'

tasks:
  build:
    desc: Build the application
    cmds:
      - go build -o bin/app ./cmd/app

  test:
    desc: Run all tests
    cmds:
      - go test ./...

  lint:
    desc: Run linters
    cmds:
      - golangci-lint run

  dev:
    desc: Run with live reload
    deps: [build]
    cmds:
      - air

What I Like

Variables and environment files:

tasks:
  deploy:
    dotenv: ['.env']
    cmds:
      - flyctl deploy --app {{.APP_NAME}}

Task dependencies with parallelism:

tasks:
  ci:
    deps: [lint, test, build]

Dependencies run in parallel by default. No need to wire up & and wait.

Conditional execution:

tasks:
  generate:
    sources:
      - 'proto/**/*.proto'
    generates:
      - 'gen/**/*.go'
    cmds:
      - buf generate

The task only runs if source files are newer than generated files.

When to Keep Make

If your project already has a Makefile and the team is comfortable with it, switching gains you nothing. Taskfile shines on new projects and for teams that are tired of debugging tab-vs-space issues.