I Taught Maven to Be an Introvert | PVR Labs
← Back to Articles<br>I Taught Maven to Be an Introvert
How a small Bash wrapper reduced successful Maven output by more than 99.7% while preserving useful diagnostics for coding agents.
by Ted Kupolov · July 30, 2026
Maven is excellent at building Java projects.
It is also extremely talkative.
That verbosity is usually harmless when a developer is reading a terminal. For a coding agent, however, several thousand bytes of routine build output can displace source code, instructions, and the actual failure from the model’s working context.
So I built mvn-lite: a small, deterministic Bash wrapper that keeps successful Maven runs to one line and extracts only bounded, actionable evidence from failures.
I call it Introverted Maven .
agent-visible output
Vanilla Maven████████████████████████████████6,753 bytes
mvn-lite▏16 bytes
More than 99.7% less output
In a real four-module Java application, successful output fell from 6,753 bytes to 16 bytes ,<br>and an invalid lifecycle failure fell from 2,730 bytes to 228 bytes . Maven’s exit status<br>was preserved, complete failure logs were retained, and Maven arguments were not echoed in compact failure<br>output.
Full measurements and methodology are available in the compatibility experiment report.
The goal is not to replace Maven’s diagnostics. It is to keep them from consuming an agent’s context unless<br>they are needed.
The problem with ordinary Maven output
A routine Maven test run can produce dozens or hundreds of lines covering routine details such as:
reactor ordering
plugin execution
compiler phases
test totals
Most of this is useful when investigating a build, but almost none is useful when it succeeds.
A coding agent usually needs to know only:
PASS · 4.240 s<br>If the build fails, the agent needs a compact answer to a different question:
What is the next actionable thing I should inspect or fix?
A compact test failure might look like:
FAIL<br>Failure summary:<br>Test: com.example.AppTest.shouldRejectInvalidInput<br>Exception: java.lang.AssertionError: expected 400
Full Maven log:<br>/project/.agent-logs/maven/maven-20260730-100000-12345.log
Re-run with --full for complete live output.<br>The raw Maven output still matters. It simply does not need to occupy the main conversation by default.
Maven’s -q option is too blunt for this use case: it suppresses output before the wrapper can inspect it. mvn-lite captures normal Maven output privately, so it can still surface failing tests, compiler errors, unresolved dependencies, failed goals, and immediate causes when a build fails.
What mvn-lite does
In compact mode, mvn-lite prefers the project’s executable ./mvnw, then falls back to mvn from PATH. It adds batch mode and disables transfer progress and color when equivalent options were not already supplied, then:
captures complete output locally;
preserves Maven’s exit status;
prints a one-line success or bounded failure summary;
retains failed logs and points to the complete log;
falls back to a bounded tail for unknown failures.
Successful logs are deleted by default but can be preserved with --keep-log. Ordinary Maven<br>output remains available through --full.
mvn-lite targets common local workflows: build, test, package, install, and verify. It recognizes high-value categories including compiler, test, dependency-resolution, failed-goal, and common Maven command errors.
Unknown output receives a bounded log tail rather than an invented interpretation, and the raw log remains authoritative.
Testing it in a real application
I tested mvn-lite in a real four-module Maven application. The selected module ran 102 unit tests using Maven 3.9.16 and the system-provided Bash 3.2 on macOS. The comparison covered vanilla Maven, the application’s former project-specific low-noise helper, and mvn-lite.
Bytes from stdout and stderr were the primary metric because they are exact and tokenizer-independent.<br>Estimated tokens use ceil(output bytes / 4) for relative comparison, not as an exact<br>model-token or billing measurement.
Successful build results
The successful run selected one module and ran its tests:
./mvnw -B -ntp -Dstyle.color=never -pl common test
RunnerBytesLinesEstimated tokens
Vanilla Maven6,75390~1,689<br>Former project-specific helper181~5<br>mvn-lite161~4
mvn-lite produced PASS · 3.944 s, reducing successful agent-visible output by more<br>than 99.7% . It effectively matched the former helper; the two-byte difference is<br>operationally meaningless.
As an additional real-world check, I also ran mvn-lite against the Scriptella reactor under JDK 17. The normal Maven run produced hundreds of lines, while mvn-lite completed with a single PASS · 11.137 s line. See the Scriptella smoke test.
Failure results
The initial failure experiment invoked an invalid Maven lifecycle phase:
./mvnw definitely-not-a-maven-phase<br>The first mvn-lite version was smaller than vanilla Maven and the former helper, but it...