{"slug": "reducing-maven-stdout-noise-by-99-while-keeping-failure-traces", "title": "Reducing Maven stdout noise by 99% while keeping failure traces", "summary": "A new Bash wrapper called mvn-lite reduces Maven build output for coding agents by 99%, cutting successful output from 6,753 bytes to 16 bytes in a real four-module Java application, while preserving exit status and failure traces. Developer Erik B. built the tool to prevent routine build logs from displacing source code and instructions in an agent's context, and it retains complete failure logs for actionable debugging.", "body_md": "Maven is excellent at building Java projects.\n\nIt is also extremely talkative.\n\nThat 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.\n\nSo I built [ mvn-lite](https://github.com/ejboy/agent-scripts): a small, deterministic Bash wrapper that keeps successful Maven runs to one line and extracts only bounded, actionable evidence from failures.\n\nI call it **Introverted Maven**.\n\nVanilla Maven████████████████████████████████6,753 bytes\n\nmvn-lite▏16 bytes\n\nIn a real four-module Java application, successful output fell from **6,753 bytes to 16 bytes**,\nand an invalid lifecycle failure fell from **2,730 bytes to 228 bytes**. Maven’s exit status\nwas preserved, complete failure logs were retained, and Maven arguments were not echoed in compact failure\noutput.\n\nFull measurements and methodology are available in the [compatibility experiment report](https://github.com/ejboy/agent-scripts/blob/main/experiments/test/PVR-LABS-FINANCIAL-ENGINE-APP.md).\n\nThe goal is not to replace Maven’s diagnostics. It is to keep them from consuming an agent’s context unless they are needed.\n\n## The problem with ordinary Maven output\n\nA routine Maven test run can produce dozens or hundreds of lines covering routine details such as:\n\n- reactor ordering\n- plugin execution\n- compiler phases\n- test totals\n\nMost of this is useful when investigating a build, but almost none is useful when it succeeds.\n\nA coding agent usually needs to know only:\n\n```\nPASS · 4.240 s\n```\n\nIf the build fails, the agent needs a compact answer to a different question:\n\nWhat is the next actionable thing I should inspect or fix?\n\nA compact test failure might look like:\n\n```\nFAIL\nFailure summary:\n  Test: com.example.AppTest.shouldRejectInvalidInput\n  Exception: java.lang.AssertionError: expected 400\n\nFull Maven log:\n  /project/.agent-logs/maven/maven-20260730-100000-12345.log\n\nRe-run with --full for complete live output.\n```\n\nThe raw Maven output still matters. It simply does not need to occupy the main conversation by default.\n\nMaven’s `-q`\n\noption is too blunt for this use case: it suppresses output before the wrapper can inspect it. `mvn-lite`\n\ncaptures normal Maven output privately, so it can still surface failing tests, compiler errors, unresolved dependencies, failed goals, and immediate causes when a build fails.\n\n## What `mvn-lite`\n\ndoes\n\nIn compact mode, `mvn-lite`\n\nprefers the project’s executable `./mvnw`\n\n, then falls back to `mvn`\n\nfrom `PATH`\n\n. It adds batch mode and disables transfer progress and color when equivalent options were not already supplied, then:\n\n- captures complete output locally;\n- preserves Maven’s exit status;\n- prints a one-line success or bounded failure summary;\n- retains failed logs and points to the complete log;\n- falls back to a bounded tail for unknown failures.\n\nSuccessful logs are deleted by default but can be preserved with `--keep-log`\n\n. Ordinary Maven\noutput remains available through `--full`\n\n.\n\n`mvn-lite`\n\ntargets 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.\n\nUnknown output receives a bounded log tail rather than an invented interpretation, and the raw log remains authoritative.\n\n## Testing it in a real application\n\nI tested `mvn-lite`\n\nin 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`\n\n.\n\nBytes from stdout and stderr were the primary metric because they are exact and tokenizer-independent.\nEstimated tokens use `ceil(output bytes / 4)`\n\nfor relative comparison, not as an exact\nmodel-token or billing measurement.\n\n## Successful build results\n\nThe successful run selected one module and ran its tests:\n\n```\n./mvnw -B -ntp -Dstyle.color=never -pl common test\n```\n\n| Runner | Bytes | Lines | Estimated tokens |\n|---|---|---|---|\n| Vanilla Maven | 6,753 | 90 | ~1,689 |\n| Former project-specific helper | 18 | 1 | ~5 |\n`mvn-lite` | 16 | 1 | ~4 |\n\n`mvn-lite`\n\nproduced `PASS · 3.944 s`\n\n, reducing successful agent-visible output by more\nthan **99.7%**. It effectively matched the former helper; the two-byte difference is\noperationally meaningless.\n\nAs an additional real-world check, I also ran `mvn-lite`\n\nagainst the [Scriptella](https://scriptella.org/) reactor under JDK 17. The normal Maven run produced hundreds of lines, while `mvn-lite`\n\ncompleted with a single `PASS · 11.137 s`\n\nline. See the [Scriptella smoke test](https://github.com/ejboy/agent-scripts/blob/main/experiments/test/SCRIPTELLA-MVN-LITE-SMOKE-TEST.md).\n\n## Failure results\n\nThe initial failure experiment invoked an invalid Maven lifecycle phase:\n\n```\n./mvnw definitely-not-a-maven-phase\n```\n\nThe first `mvn-lite`\n\nversion was smaller than vanilla Maven and the former helper, but it repeated\nMaven’s complete list of valid lifecycle phases. The actionable information was only:\n\n```\nMaven: Unknown lifecycle phase \"definitely-not-a-maven-phase\"\n```\n\nI updated the parser to shorten recognized Maven command errors while preserving the complete original message in the raw log.\n\n### Actionable failure output after parser improvement\n\nAgent-visible UTF-8 bytes, stdout + stderr\n\n**2,730**\n\n**1,393**\n\n`mvn-lite`\n\n**873**\n\n```\nUpdated mvn-lite228\n```\n\n73.9% less output than the original `mvn-lite`\n\nThe updated wrapper reduced output by **91.6%** relative to vanilla Maven, **83.6%** relative to the former project-specific helper, and **73.9%** relative to the first `mvn-lite`\n\nimplementation. It still preserved Maven’s exit status, the invalid phase, the complete-log location, and rerun guidance.\n\n## Extracting the immediate cause\n\nSome Maven plugin failures include the useful cause on the same line as the failed goal:\n\n```\nFailed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.2.5:test\n(default-test) on project app:\nExecution default-test failed:\nUnable to create temporary directory\n```\n\nA useful compact summary needs both:\n\n```\nGoal: org.apache.maven.plugins:maven-surefire-plugin:3.2.5:test (default-test)\nCause: Unable to create temporary directory\n```\n\n`mvn-lite`\n\nextracts at most one immediate cause from bounded forms such as:\n\n```\nExecution ... failed: <cause>\n```\n\nIt does not reconstruct arbitrary exception chains or stack traces.\n\nDuring the final application integration, a restricted workspace prevented Surefire from creating its normal `target/surefire`\n\ndirectory. The installed wrapper preserved exit status 1, retained the complete log, identified the Surefire goal, surfaced `Unable to create temporary directory`\n\n, and remained bounded.\n\nThe same build passed after normal filesystem permissions were restored.\n\n## Try `mvn-lite`\n\nin your project\n\nTo try the latest version:\n\n```\ncurl -fsSL \\\n  https://raw.githubusercontent.com/ejboy/agent-scripts/main/scripts/mvn-lite \\\n  -o mvn-lite\nchmod +x mvn-lite\n```\n\nReview the script before running it in a sensitive repository. For a reproducible vendored copy, replace\n`main`\n\nwith a release tag such as `v0.1.0`\n\n.\n\nArguments pass through to Maven. Use `--full`\n\nwhen ordinary Maven output is needed:\n\n```\n./mvn-lite test\n./mvn-lite -pl common test\n./mvn-lite --full test\n./mvn-lite --help-mvn-lite\n```\n\n## Why not summarize the logs with an LLM?\n\n`mvn-lite`\n\nextracts the useful signal locally instead of spending agent tokens on an LLM summary\nor sending repository logs outside the environment. It requires no API key and falls back to a bounded log\ntail instead of making a probabilistic guess.\n\n## Limitations\n\nThis was a focused compatibility and adoption experiment: one real multi-module application, one successful module build, one synthetic lifecycle error, one real Surefire environmental failure, warm incremental state, and single measured runs.\n\nThis article summarizes the main findings. The [complete experiment report](https://github.com/ejboy/agent-scripts/blob/main/experiments/test/PVR-LABS-FINANCIAL-ENGINE-APP.md) contains the full environment, controls, intermediate results, checksums, and supporting evidence.\n\nThe results do not establish a fixed savings percentage, diagnostic parity for every Maven plugin or failure category, or that Maven itself runs faster.\n\nThe claim is narrower:\n\nFor the measured local-development scenarios,\n\n`mvn-lite`\n\ndramatically reduced agent-visible output while preserving the exit status, actionable failure evidence, and access to the complete raw log.\n\n## The broader lesson\n\nCoding agents change the economics of command-line output.\n\nTraditional build tools assume that console output is cheap. A developer can scroll, search, collapse, or ignore it.\n\nFor an agent, output competes directly with source code, requirements, conversation history, repository context, and the actual diagnostic. A tool designed for agent workflows should:\n\n- Make success extremely small.\n- Preserve exit status and actionable failure evidence.\n- Retain complete diagnostics outside the main context.\n- Bound unknown-output fallbacks and avoid echoing sensitive arguments.\n- Preserve an escape hatch to ordinary output.\n\nThat is what `mvn-lite`\n\nis trying to do.\n\nMaven still knows everything it knew before.\n\nIt has simply learned when not to say it.\n\nTry `mvn-lite`\n\nin an existing Maven project. Real-world failure cases and feedback are\nespecially useful.", "url": "https://wpnews.pro/news/reducing-maven-stdout-noise-by-99-while-keeping-failure-traces", "canonical_source": "https://pvrlabs.xyz/articles/introverted-maven.html", "published_at": "2026-08-11 14:59:01+00:00", "updated_at": "2026-08-11 15:12:25.180340+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["mvn-lite", "Maven", "Erik B."], "alternates": {"html": "https://wpnews.pro/news/reducing-maven-stdout-noise-by-99-while-keeping-failure-traces", "markdown": "https://wpnews.pro/news/reducing-maven-stdout-noise-by-99-while-keeping-failure-traces.md", "text": "https://wpnews.pro/news/reducing-maven-stdout-noise-by-99-while-keeping-failure-traces.txt", "jsonld": "https://wpnews.pro/news/reducing-maven-stdout-noise-by-99-while-keeping-failure-traces.jsonld"}}