Aider with Makefile-driven projects: integrating with non-standard build flows
Published 2026-01-13 by Owner
Many projects don’t have npm test or pytest as the canonical test command. They have Makefiles. Aider’s auto-test feature accepts any shell command, so Makefile integration works — but the gotchas matter.
The basic setup
In .aider.conf.yml:
auto-test: true
test-cmd: make test
Aider runs make test after each commit. If it fails, aider sees the output and tries to fix the issue.
For most projects, this is enough. The model gets feedback; the loop closes.
Gotcha 1: long-running tests
Many Makefile-driven test commands are slow. Integration tests, hardware-in-the-loop tests, full builds. If make test takes 10 minutes, aider’s iteration loop is 10 minutes per attempt.
For long-running tests, configure a faster subset for aider:
test-cmd: make test-quick
Where make test-quick runs only the unit tests or a fast subset. The full make test runs in CI.
Gotcha 2: tests with side effects
Some Makefile-driven tests have side effects: starting databases, modifying files, calling external services. Aider runs these on every iteration; the side effects accumulate.
Mitigation: design test commands to be idempotent. If your tests fail when run twice in a row, they need fixing regardless of aider.
Gotcha 3: parallel make output
make -j8 test produces interleaved output from parallel test runners. Aider’s parser sometimes confuses the interleaving. Errors get attributed to wrong tests.
Mitigation: for aider-driven runs, use sequential output:
test-cmd: make test PARALLEL=1
Where the Makefile recognizes PARALLEL=1 and runs sequentially. Slower; aider sees clean output.
Gotcha 4: make’s exit codes
Aider relies on exit codes to know if tests passed or failed. Some Makefile patterns swallow exit codes:
test:
-pytest tests/
-clippy --check
The - prefix suppresses errors. Aider thinks tests passed even when they failed.
Fix:
test:
pytest tests/
clippy --check
Without the - prefixes. Make stops at the first failure.
A specific workflow
For a C++ project I’ve worked on:
auto-test: true
test-cmd: make -B test-fast
The -B flag forces rebuild (avoiding stale artifacts). test-fast runs the unit tests subset. Total time per iteration: ~30 seconds. Acceptable for the agent loop.
The full test suite runs in CI, where 10 minutes is fine.
Building before testing
For compiled languages, you often need a build step before tests. Some patterns:
Combined target:
test: build
./bin/test_runner
build:
cargo build
Aider runs make test; make ensures build runs first.
Separate test command for aider:
test-cmd: make build && make test-bin
Combining build and test into one shell command. Works if your shell supports it.
Pre-test hook:
If your Makefile has tests that build internally, no setup needed. Aider’s make test triggers everything.
What this enables
For Makefile-driven projects, integrating aider’s auto-test gives:
- Fast feedback on AI-generated changes
- Aider can self-correct based on test failures
- The agent loop closes without manual intervention
- Behavioral changes show up in test failures, not just compile errors
The investment is bounded — typically an hour to set up the right test command and verify aider can use it. The payoff is the agent loop working effectively in non-standard projects.
When it’s not worth it
For projects where:
- Tests are very slow (>2 min) and can’t be subsetted
- Tests require special environment (specific hardware, network access, paid APIs)
- Tests are flaky enough to confuse the agent
…auto-test may not work well. Aider can still be used; just disable auto-test and run tests manually between agent turns.
A pattern I avoid
Some teams write a wrapper script for aider:
#!/bin/bash
# aider-test.sh
make build || exit 1
make test || exit 1
make lint || exit 1
And use test-cmd: ./aider-test.sh.
This works but I find it brittle. The wrapper script is a hidden layer; debugging issues requires understanding both the script and the Makefile. Direct Makefile integration is cleaner.
Worth doing
For teams using Make as their build system, integrating with aider is worth the setup time. The alternative (manually running tests between aider turns) loses most of the agent-loop value.
The investment is small; the payoff is real. The gotchas above are predictable; addressing them takes a few hours total.
After setup, aider’s experience on a Makefile-driven project is similar to its experience on an npm-driven project. The build system isn’t the limiting factor; the underlying code structure is.