Reference
Every command, flag, format and limit in Abbreviatory v0.6.0. For a first run, the quick start is shorter. The same reference is in the code repository as docs/reference.md.
Commands
| Command | What it does |
|---|---|
abbreviatory reduce [flags] [file] |
Reduce a file, or standard input, and print the report |
abbreviatory run [flags] -- CMD |
Run a command, reduce what it prints, compare with its last run, exit with its status |
abbreviatory history [KEY] |
List the run histories, or the runs of one |
abbreviatory expand [-store dir] REF |
Print the original bytes a reference stands for |
abbreviatory serve [-addr 127.0.0.1:7878] [-token T] |
Serve reduce, expand and histories over HTTP |
abbreviatory mcp |
Serve them to a coding agent over the Model Context Protocol |
abbreviatory prune [-older 168h] [-max-size 500MB] |
Remove old stored originals |
abbreviatory formats |
List the input formats |
abbreviatory version |
Print the version |
Exit codes: run exits with the command’s own status (127 if the command isn’t found). Otherwise 0 when it worked, 1 when the work failed (unreadable input, a budget too small, a reference not in the store), 2 for a usage mistake.
Flags for reduce and run
| Flag | Default | What it does |
|---|---|---|
-budget N |
4096 | Most bytes of output. At least 512 |
-preserve LIST |
errors,failures,warnings | What is always shown or referenced. Empty for nothing |
-keep REGEX |
Also keep lines matching this. Repeatable | |
-format NAME |
auto | auto, a family (test-output, build, logs, json), or one of the formats below |
-json |
off | Print a JSON object with the counts and the report |
-no-store |
off | Don’t keep the original. The report then has no references |
-key NAME |
Keep a run history under NAME and report what changed. run names one after the project and the command |
|
-full |
off | With a history, the whole report even when nothing changed |
-warnings |
off | With a history, compare warnings with the last run too: new ones listed and marked (new), those gone listed |
-no-history |
off | run only: keep no history |
-store DIR |
cache directory | Where originals and histories are kept. Also $ABBREVIATORY_STORE |
Formats
| Name | What it reads |
|---|---|
gotest-json |
go test -json: one record per test, with its output; build failures and tests that never finished too |
gotest |
Plain and -v go test output, subtests, panics, build errors |
pytest |
pytest, verbose or not: FAILURES and ERRORS sections matched to the short summary, the warnings summary, the final count |
junit |
JUnit XML reports, one record per testcase |
cargo-test |
cargo test: every test, the failures with their output and panic message, the test result: counts. In a workspace a test is named with its crate’s test binary |
cargo |
cargo build, check and clippy: each rustc error and warning with its snippet and notes, headed by its location (at src/main.rs:12:27) |
tsc |
The TypeScript compiler, plain (src/cart.ts(9,7): error TS2322) and pretty, and watch mode; the last Found N errors is the count |
eslint |
ESLint’s stylish, compact and unix formats: each problem by file, line, column and rule |
gradle |
javac’s and kotlinc’s errors and warnings, failed tests by task, and “What went wrong” as one error with the messages repeated in it |
maven |
Compiler errors and warnings, failed tests by module with their exception and stack trace, each “Failed to execute goal” as one error; the closing advice is information |
npm |
npm and pnpm: an error block as one error headed by its code, ERR_PNPM_ errors, deprecation warnings, the audit count |
logs |
Anything that is text: levels, stack traces, Python tracebacks, Go panics |
json |
One JSON document, shown as a valid JSON outline |
diff |
git diff, git show, git log -p, diff -u and -r, merge diffs: commits, every file with its added and removed lines and a reference, then the changes. The same change in several places is shown once with a count; lock files and generated code are listed, not spelled out; conflict markers are errors, trailing whitespace a warning |
http |
curl -i, curl -v and redirect chains: status lines (4xx and 5xx are errors), the headers that matter, curl’s errors, and the body. A JSON body is outlined with its error fields kept; other bodies are read like a log |
listing |
find, fd, ls -l, ls -R, tree, du: files grouped by directory and extension, with counts, total size, the most common extensions and the largest files; “Permission denied” lines are errors |
Detection tries HTTP responses, test runners, Maven, JSON, the other build tools, diffs and listings, in that order, and reads anything else as a log. It takes colour codes out first, so CARGO_TERM_COLOR=always and eslint --color are fine.
The level of a log line comes from upper-case words near its start (ERROR, WARN, FATAL, CRITICAL and others), level= and JSON level fields, bracketed levels, glog prefixes, compiler style error: and warning:, and the first line of a panic or traceback.
The Report
[abbreviatory] <format>, <lines> (<size>), ref <ID>
<counts>
FAILED (n):
- <test> [ref ID:gN]
<the failure message>
ERRORS (<kinds>, <lines>):
- x<count> <the first line of the group> [ref ID:gN]
MATCHED --keep (...):
WARNINGS (...):
OTHER (...):
not shown: <what was left out> [ref ID:<kind>]
How the budget is spent: the header, the counts and the “not shown” lines are set aside first. Then every failure, error, keep-rule match and warning gets its one line. Then detail lines are shared out in rounds (2 each, then 6, 16 and 40), so every failure shows some of its message before any shows all of it. Other groups fill what’s left, most frequent first.
If even the header and the counts don’t fit, reduce fails and says how many bytes it needs. When an input is so small that showing it whole is no longer than reducing it, it’s shown whole.
References
A reference is ID:selector. The ID is a hash of the input, so the same input always gets the same ID.
| Selector | Expands to |
|---|---|
| none | The whole input |
gN |
The original lines of group N |
fail, error, warn, info, pass, skip |
Every line of that kind |
keep |
Every line a -keep rule matched |
L10 or L10-40 |
Those input lines |
/items/3 |
For JSON: that value, as it is in the input |
errors |
For JSON: every error field with its value |
Lines come back byte for byte, in input order.
Run History
With a history, each run is compared with the one before it. A failed test is known by its name, with its package for go test, its test binary for cargo, its task for Gradle and its module for Maven. Anything else, a log error, a compiler error or a failed build, is known by its text with numbers and IDs aside. Gradle’s “What went wrong” and Maven’s “Failed to execute goal” are known by their first line, so fixing one error under them doesn’t make them new.
Gradle (without testLogging) and Maven don’t name passing tests. A failing test missing from the next run counts as fixed if its task or module ran its tests, and as not run otherwise, such as after a compile error.
| In the report | Meaning |
|---|---|
| new | failing now, not in the last run |
| fixed (logs and compilers: gone) | failing in the last run, passing now |
| not run | a test failing in the last run that was skipped or didn’t run this time |
| still failing (logs: recurring) | failing in both, marked with how many runs in a row |
| flaky (logs: intermittent) | changed between passing and failing 3 or more times in the last 10 runs |
With -warnings, warnings are compared too, known by their text with numbers aside. New ones are listed under the summary line and marked (new), and those gone are listed with a reference into the last run; either makes the run a change. The run just before must have had -warnings too, or the report says the warnings weren’t compared. Past 50,000 kinds of warning in a run they aren’t compared either.
New failures come first in the report, marked (new). Fixed ones carry a reference into the run where they last failed. When the same failures are there as last time, the report is one line, unless you pass -full. A history keeps the last 50 runs and is removed after 90 days unused.
MCP Server
abbreviatory mcp speaks the Model Context Protocol on standard input and output. Add it to a coding agent as the command abbreviatory mcp; for Claude Code that’s claude mcp add abbreviatory -- abbreviatory mcp. It offers four tools:
| Tool | What it does |
|---|---|
run |
Runs a command given as an array, such as ["go", "test", "./..."], reduces what it prints and compares with the last run. Takes cwd, timeout_seconds (600 by default), stdin, key and no_history |
reduce |
Reduces output given as text, or a file given as path |
expand |
Returns the original lines behind a reference, up to 4 MB unless max_bytes says more |
history |
Lists the histories, or the runs of one with key |
Every tool also takes budget, format, preserve, keep, full, warnings and no_store, as the flags. A command that runs past its time limit, or whose request the agent cancels, is stopped along with what it started.
HTTP Service
abbreviatory serve listens on 127.0.0.1:7878. To listen where other machines can reach it, give it a token with -token or $ABBREVIATORY_TOKEN; it then asks every request for Authorization: Bearer TOKEN.
| Request | What it does |
|---|---|
POST /reduce |
The body is the input, the options are query parameters named as the flags. Returns the JSON of reduce -json, or the report alone with Accept: text/plain |
GET /expand/{ref} |
The original bytes behind a reference |
GET /runs, GET /runs/{key} |
The histories, or one history’s runs |
GET /healthz |
Status and version, without the token |
The command line, the MCP server and the HTTP service share one core, and the test suite checks they give the same reports, expansions and histories on every fixture.
GitHub Action
abbreviatory/engine@v0.6.0 runs a command, writes the report to the job summary, keeps the run history in the Actions cache and fails the step when the command fails.
- uses: abbreviatory/engine@v0.6.0
with:
run: go test -json ./...
warnings: true
| Input | Default | What it does |
|---|---|---|
run |
The command, one shell command line run with bash | |
working-directory |
. |
Where to run it |
key |
History name; empty means one made from the directory and the command | |
budget, format, keep, warnings, full |
As the flags; keep takes one expression per line |
|
summary |
true | Append the report to the job summary |
cache |
true | Keep the history in the Actions cache |
cache-key |
abbreviatory-<job>-<matrix index> |
Start of the cache key; jobs that should share a history give the same one |
fail |
true | Fail the step when the command fails; false reports only |
version |
the pinned release | An Abbreviatory release, or latest |
Outputs: exit-code, result (pass, fail, or error when Abbreviatory itself couldn’t run, which fails the step whatever fail says), new, fixed, failing, new-warnings, report (a text file) and json. The action needs bash and jq, which GitHub’s runners have.
Limits in v0.6.0
- Known formats only. Free prose, or a log format it doesn’t recognise, is reduced only by folding repeats and finding level words.
- Numbers don’t count for grouping. Two errors that differ only in a number, a port or a status code are one group. The first is shown, and the count says how many.
- Some inputs are read whole. JSON documents and JUnit reports are read in one piece, up to 256 MB. Logs and test output stream with no size limit.
- References need the stored original. With
-no-store, or after pruning, they can’t be expanded. - Plain go test and pytest only name failures. Without
-v, a failing test that disappears counts as fixed, even if it was deleted or skipped. - History tracks failures and errors, and warnings with
-warnings. Keep-rule matches aren’t compared, and warnings are compared by kind, not by how often they appear. A log error whose wording changes counts as new. - CI needs the store kept between runs. CI machines start empty, so cache the store directory, or every run is run 1.
- HTTP bodies end at the next status line. A body with no final newline that runs straight into the next response (curl
-Lwith-i) runs into it. A JSON body longer than 64 kB on one line, or over 16 MB, is read like a log. - Listings guess some directories.
du -acan’t tell a file without an extension from a directory, and intreeoutput without its closing count an empty directory counts as a file. - The HTTP service has no TLS. Put it behind a proxy that has, if it’s reachable beyond the machine.
- Build tools in their default human formats. Not cargo’s
--message-format=jsonor ESLint’s JSON and SARIF. A tool run inside another (tsc throughnpm run build) is read as the first one found. Yarn’s output is read as a log.cargo test -- --nocapturecan put a test’sokon a later line, and then the test isn’t counted. In tsc’s watch mode, errors from earlier compilations stay in the report. - The MCP
runtool runs what the agent asks. It runs commands as you, the same as an agent’s own shell tool would.