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.
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ística | Make | Just |
|---|---|---|
| Indentação | apenas tabs (erro se usar espaço) | tabs ou espaços |
| Comandos que não geram arquivo | exigem .PHONY | default |
| Argumentos | make deploy ENV=prod | just deploy prod |
| Listar comandos | hacks com grep/awk | just --list nativo |
| Instalação | já vem em Unix/macOS | brew install just ou cargo install just |
O que isso muda no dia a dia:
- 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.
.PHONYsome. Cada comando é comando por padrão. Se você algum dia criou um alvoteste um diretóriotest/apareceu, sabe por que isso importa.- A CLI do projeto vira documentação. Rodar
justsem 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 testsem 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 buildtem suporte nativo aBuildMethod: makefilee espera um arquivo chamado literalmenteMakefilecom alvos no formatobuild-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 --listvira onboarding de 30 segundos. Quando volto a um projeto meu depois de 3 meses, rodojuste 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.