Built for AI agents
An agent pays for every row it reads and acts on every number it is given. gnarl is built for that as much as for people:
- Economical by default. The report lists only what is over a limit;
--topand--functionnarrow it further,--allwidens it. - Every number explained.
--explainlists each construct counted and where, so an agent can aim a refactor and check a count, rather than guess at a score. - The cut, planned before it is made. For a function over a limit,
--explainnames the ranges worth lifting out;--explain path:A-Bsays what a function of those lines would score, the parameters it would take, what it would give back, and which jumps leave the lines. - One loop. Explain, lift the first suggestion,
gnarl --diff HEAD: each touched function before and after, a mixed change called mixed rather than worse, and a last line saying whether anything is over a critical limit now. - Nothing to scrape.
--jsonand--format xmlcarry every field and everything said on stderr, versioned by aschemanumber. - Every message says what to do next. A failing
--checknames the function, the metric, the limit, and the--explainto run.
The skill
The binary teaches its own use:
gnarl skill # the guide
gnarl skill counts output # those topics of it
gnarl skill --all # the whole guide
gnarl skill --install ~/.skills # write ~/.skills/gnarl/SKILL.md
gnarl skill prints the loop, the names gnarl gives functions, the exit statuses and what catches agents out, and a line on each topic it leaves out until asked: counts, the counting rules with measured examples; output, every field of each format; thresholds, the limits and complexity.zon. So a load costs less than half the whole guide, and the reference is there when the job needs it. What --install writes has the agent run gnarl skill, so it is never older than the gnarl installed. The guide is embedded in the binary and tested against it: every example in it is measured as it says, and every metric, format and flag gnarl has is named in it.
An agent given only gnarl’s guide and a copy of a function at cognitive 48 brought it to 5, with two helpers, using the regions and range estimates to choose the cuts before making them. Its estimates matched the result exactly.