Por que tenho preferido justfile a Makefile

Substituí Makefile por justfile nos projetos novos. Não é militância: é preferência com alguns motivos técnicos — e um lugar onde Makefile ainda vence.

· 5 min de leitura
Ilustração editorial de cartões justfile e Makefile sobre uma mesa com terminal ao fundo.

Make é padrão da indústria há cinco décadas. Está em quase todo Unix, em todo macOS, e todo dev já debugou pelo menos uma vez um “missing separator” porque confundiu tab com espaço. Mesmo assim, em 2026 tenho substituído Makefile por justfile como padrão nos projetos novos. Não é militância — é preferência com alguns motivos técnicos e um lugar concreto onde Makefile continua vencendo por restrição.

O que justfile é (e o que não é)

Just é um command runner escrito em Rust. Não é um sistema de build. A própria documentação do projeto comprime bem: just é para rodar comandos, não para modelar grafo de build.

Tradução prática: Make rastreia timestamps de arquivos e recompila só o que mudou. Just não faz nada disso — ele roda o comando que você pediu, ponto. Se você usa Makefile há anos só para ter make dev, make lint, make deploy, está usando 5% do Make. Esse 5% é o escopo inteiro do just.

Três diferenças que pesam na prática

Resumo sem romantismo, da tabela de comparação:

CaracterísticaMakeJust
Indentaçãoapenas tabs (erro se usar espaço)tabs ou espaços
Comandos que não geram arquivoexigem .PHONYdefault
Argumentosmake deploy ENV=prodjust deploy prod
Listar comandoshacks com grep/awkjust --list nativo
Instalaçãojá vem em Unix/macOSbrew install just ou cargo install just

O que isso muda no dia a dia:

  1. O erro de tab some. Parece bobagem até você perder 10 minutos por um espaço invisível em arquivo colado de repo alheio. Some.
  2. .PHONY some. Cada comando é comando por padrão. Se você algum dia criou um alvo test e um diretório test/ apareceu, sabe por que isso importa.
  3. A CLI do projeto vira documentação. Rodar just sem argumento lista todos os comandos com seus comentários de #. É documentação executável — a mesma coisa que todo repo grande tenta fazer com README de “useful commands” e ninguém mantém atualizado.

Onde Makefile ainda vence

Três casos em que Makefile é a resposta certa, não o default preguiçoso:

  • Build incremental de verdade. Monorepo C++ grande, pipeline com codegen e assets derivados, ou qualquer coisa que precise recompilar só o que mudou com base em timestamp. Just não rastreia arquivos — sempre roda o comando. Aqui, Make (ou Task, ou Bazel) é a ferramenta correta.
  • Ubiquidade absoluta. Se “o dev clona o repo e roda make test sem instalar nada” é requisito duro (CI minimalista, ambiente efêmero), Make ainda ganha. Just é um binário estático fácil de instalar, mas é mais uma dependência de tooling.
  • AWS SAM. O sam build tem suporte nativo a BuildMethod: makefile e espera um arquivo chamado literalmente Makefile com alvos no formato build-NomeDaFuncao. Não há suporte nativo para justfile. É restrição da ferramenta de deploy, não do runtime Lambda — o Lambda em si aceita qualquer artefato.

O padrão que uso nesse caso é ponte: um Makefile minúsculo que apenas delega para o justfile.

build-MyFunction:
	just build-lambda $(ARTIFACTS_DIR)

O Makefile vira interface para o SAM, e a lógica real mora no justfile — onde ela é legível. O custo são três linhas de Makefile por função. Pago sem reclamar.

Por que prefiro mesmo com os contras

A parte técnica explica 60% da preferência. Os outros 40% são gosto — admito antes de vender como “decisão racional pura”:

  • A sintaxe sai do meu caminho. Não preciso lembrar em qual Makefile eu estava quando vou escrever um alvo novo. Just tem um jeito só de fazer cada coisa.
  • just --list vira onboarding de 30 segundos. Quando volto a um projeto meu depois de 3 meses, rodo just e lembro o que existe. O mesmo hábito com Makefile sempre me levou a abrir o arquivo e lê-lo.
  • Shebang por recipe. Dá pra misturar shell, Python, Node no mesmo justfile sem contorcionismo. Uso pouco — mas a flexibilidade existe sem peso sintático.
  • É bonito. Gosto de ler. Isso conta, mesmo que não seja argumento técnico.

Se você é produtivo em Makefile, nada do que está acima justifica migração forçada. Se está começando projeto novo em 2026, vale pensar qual ferramenta entra por default.

O que considerei e não escolhi

Três alternativas que apareceram na mesma pesquisa e onde cada uma cabe melhor:

  • Taskfile (go-task) — YAML, checksums de arquivos, pula tarefas se o input não mudou. Se o projeto precisa de inteligência de build leve ou CI/CD complexo, Task é melhor que Just.
  • Mage — código Go puro, sem DSL nova. Se o time é fluente em Go e as tarefas têm lógica complexa, Mage ganha. Em time misto, perde.
  • Mise — gestor de versões de linguagens que também roda tarefas (mise run). Se já uso mise para versionar Node/Python, poderia consolidar. Ainda não fiz a conta — continua na lista.
  • Earthly — cada etapa roda em container. Garante build local idêntico ao do CI. É resposta para outro problema (reprodutibilidade), não substituto direto do Make.

Nenhum desses me convenceu como default para “abrir projeto qualquer e rodar just na hora”. É o menor atrito para a primeira tarefa — e foi o critério que ganhou.

Fecho

A regra simples que uso hoje:

  • Projeto puro command-runner e sem SAM envolvido → justfile.
  • Projeto com SAM → justfile com ponte em Makefile mínimo.
  • Build incremental real por timestamp → Makefile (ou Task).

Se você usa Makefile e funciona, não há urgência. Se está começando projeto novo, experimente brew install just, escreva 5 comandos e rode just sem argumento. Em 10 minutos dá pra decidir se cabe no seu hábito ou não. Foi o que fiz.

Discussão