Why I Ditched Make for Just
After fifteen years of wrestling with Makefiles that look like they were written by caffeinated cryptographers, I’ve found something better. It’s called Just, and before you roll your eyes at another “revolutionary” build tool, hear me out. This isn’t another JavaScript framework that’ll be obsolete by next Tuesday.
Just is what happens when someone looks at Make and asks the obvious question: why are we still debugging tab-versus-space issues in 2024? Created by Casey Rodarmor (yes, the same person behind the Rust-based file searcher fd), Just takes the best parts of Make and throws out the archaeological cruft that makes senior developers weep into their coffee.
The syntax is clean, the error messages are actually helpful, and it runs the same way on every platform. I know, I know. “It runs the same on Windows” sounds like marketing speak, but I’ve been burned enough times by cross-platform builds to appreciate when something just works.
The Beauty Is in the Simplicity
Here’s what sold me. In Make, if you want to pass arguments to a recipe, you end up with something that looks like line noise. In Just, you write `just deploy staging` and it works exactly like you’d expect. No variable gymnastics, no mysterious automatic variables that change behavior based on the phase of the moon.
The justfile syntax reads like pseudocode that actually runs. Want to set up dependencies between tasks? Write `deploy: build test` and you’re done. Need to run something in a specific directory? Use `cd backend && cargo build` without worrying about whether your shell will cooperate. Just handles the shell invocation sanely across platforms, which is more valuable than it sounds when you’re debugging why your CI pipeline works on Linux but fails on the intern’s Windows laptop.
Variables work the way you’d expect them to. Environment variables are just there. You can set defaults, override them, and even use command substitution without feeling like you’re performing dark magic. When I showed our DevOps team how to replace a 200-line Makefile with a 50-line justfile that did the same thing but more reliably, the silence was deafening. Good silence.
Real-World Impact on Development Speed
The productivity gains hit different when you’re not constantly context-switching to debug build scripts. Last month, our team onboarded three new developers. Instead of the usual ritual of explaining why they need to install specific versions of Make and why certain recipes fail on macOS, I told them to run `just setup`. Ten minutes later, they had working development environments.
Just’s command discovery changes how you interact with projects. Run `just` without arguments and it lists available recipes with descriptions. No more digging through README files or asking in Slack what commands are available. The autocomplete works out of the box with most shells, so you can tab-complete your way through deployments like a civilized human being.
The real test came during our last major release. We had multiple services to deploy in sequence, database migrations to run, and feature flags to toggle. The old Makefile approach meant checking twelve different repositories for the correct incantation. With Just, we centralized the orchestration in our infrastructure repo. `just release v2.1.0` handled everything, with proper error handling and rollback procedures. When something failed halfway through (because of course it did), the error message told us exactly which step broke and why.
Integration That Actually Makes Sense
Just plays nicely with existing toolchains without trying to replace them. It’s not trying to be Bazel or Buck. It’s not reinventing package management. It’s doing the job of coordinating commands and doing it well. Our Rust projects still use Cargo, our Node projects still use npm scripts, and our Python projects still use Poetry. Just sits on top, orchestrating the chaos into something resembling order.
The conditional execution features solve real problems without overengineering solutions. Need to skip certain steps in CI? Use `just –dry-run` to see what would execute, or add simple conditionals based on environment variables. Want to run different commands based on the operating system? Just has built-in functions that work without requiring you to remember arcane shell syntax.
Docker integration is where Just really shines. Instead of maintaining separate shell scripts for local development and containerized builds, you can define recipes that work in both contexts. Being able to switch between running commands locally and in containers has eliminated an entire class of “works on my machine” issues that used to plague our development workflow.
The Pragmatic Choice for Teams That Ship
Look, I’m not saying Just will solve all your problems. You’ll still have to deal with dependency hell, flaky tests, and that one service that nobody understands but everyone’s afraid to touch. But it’ll solve the annoying problem of build tool configuration being harder than the actual work you’re trying to do.
The learning curve is refreshingly flat. If you know Make, you can be productive with Just in an afternoon. If you don’t know Make, you can probably be productive with Just in an hour. The documentation is written by someone who actually uses the tool, not by a technical writer who’s never seen a command line.
Installation is trivial on every platform that matters. The binary is small, fast, and doesn’t require a complex runtime. It’s the kind of tool that makes you wonder why we tolerated the old way for so long. Sometimes the best innovations are the ones that make existing workflows work better, without requiring you to rewrite everything or learn a new programming language disguised as a build system.
Have you given Just a try in your projects? I’m curious about other workflow automation tools that have surprised you with their elegance. Drop me a line and tell me about the under-the-radar tools that have made your development life better.