RuboCop 1.92: Agents Welcome
RuboCop 1.92 is out! Last time I talked about the long road to 2.0. This time the theme is more down to earth, and probably closer to how a lot of you use RuboCop today - AI coding agents.
These days plenty of RuboCop runs aren’t started by a person at all. Claude Code, Codex, Cursor and friends run it after every batch of edits, read whatever it prints and try to fix what it found. That’s a very different user from the one RuboCop was built for. An agent has endless patience, but everything RuboCop prints ends up in its context window, and it can’t glance at a terminal and tell what’s obviously noise. So I spent most of this cycle making RuboCop a better citizen in that world.
Output an agent can act on
--format json now tells you exactly what autocorrection would do with each offense.
Every correctable offense carries the edits, and whether a plain rubocop -a would
apply them:
"correction": {
"safe": true,
"edits": [
{
"start_line": 1,
"start_column": 6,
"last_line": 1,
"last_column": 12,
"begin_pos": 5,
"end_pos": 12,
"replacement": "'hello'"
}
]
}
A cop that crashes on a file is now listed with that file’s results, instead of only
on stderr, where nothing that parses JSON ever looks. (And the --parallel notice no
longer goes to stdout, where it used to break the JSON output. Oops.)
There are also a few new options aimed squarely at agents (humans are welcome to use them too):
--max-offenses-per-cop=Ncaps how many offenses each cop reports. A legacy codebase can easily have thousands ofStyle/StringLiteralsoffenses, and an agent doesn’t need to read all of them to get the idea.--explain COPprints what a cop checks, its good and bad examples, its configuration as your project resolves it, and whether it autocorrects. Offense messages are terse by design, and often that’s not enough to fix the code the way the cop actually wants.--show-copsand--show-docs-urlnow complain about cop names they don’t recognize instead of silently ignoring them. Agents make up plausible-sounding cop names more often than you’d think.
A much better MCP server
Koichi added an experimental MCP server back in RuboCop 1.85, and in this release it got a serious overhaul:
rubocop_inspectionanswers in the same shape as--format jsoninstead of as LSP diagnostics. LSP diagnostics are great for editors, but an agent had to wade through 0-based lines and quick fixes it had no use for, and the results were about twice as big.- A new
rubocop_explaintool does what--explaindoes. - Inspection and autocorrection take
only,exceptandchanged, so an agent can check just the files it touched, or justLint. - Autocorrection can preview its changes as a diff, reports the offenses it couldn’t fix, and leaves alone the files it has nothing to correct in.
- Cops with
AutoCorrect: contextual, likeLint/UselessAssignment, are held back by default, since the code is probably mid-edit. An agent that’s done editing can ask for them withcontextual: true. - A cop crashing on one file no longer fails the entire request.
The server is still marked experimental, but it’s in a much better place now. If you’re using it with your agent of choice, I’d love to hear how it goes.
Agents and rubocop:disable
There’s a new AI Agents page in the docs that covers all of the above,
plus a few lines you can drop into your AGENTS.md or CLAUDE.md so the agent knows
how your project wants RuboCop run.
It also deals with my favorite agent “fix” - the # rubocop:disable that makes the
offense go away. Banning directives outright is too blunt, since some offenses really
are better left alone, but you can make the agent explain itself:
Style/DisableCopsWithinSourceCodeDirective:
Enabled: true
AllowWithReason: true
Now every directive needs a -- justification, and whoever reviews the change gets to
decide whether the reason holds up.
Sandboxes
More and more agents run in sandboxes that only allow access to the project
directory. Filesystem calls outside of it fail with EPERM, and RuboCop was mostly
prepared for EACCES, so a cache it couldn’t write to took the whole run down with
it. Now it just carries on without the cache. One more crash of that kind, in the
lookup of your target Ruby version, has a fix lined up for the next release.
Autocorrection you can trust
This one isn’t specific to agents, but agents are the ones who suffer the most from
it. A person notices when -a produces garbage. An agent might happily build on top
of it. This release has a mountain of bug fixes, and most of them are about
autocorrection - dozens of infinite loops between cops, and an even longer list of
corrections that produced broken (or subtly different) code. Plenty of them came out
of a systematic audit of our autocorrections, and Koichi, viralpraxis and
Starlexxx fixed a staggering number of them.
The rest of the release
Lint/UselessAssignmentnow catches a variable that a block keeps assigning but nothing ever reads.Security/JSONLoadnow reportsJSON.load(src, create_additions: false). Before json 2.17 the option is ignored in that position, so the “safe” call wasn’t safe at all.JSON.load(src, nil, create_additions: false)works everywhere.Style/NegativeArrayIndexis now marked as unsafe.--changed,--diffand the SARIF formatter, all new in 1.91, got a round of fixes.- RuboCop no longer loads
net/httpon every run, only when it fetches a remote config. regexp_parser2.11.3 or newer is now required.
The release notes have the full list.
Epilogue
Agents are already a big part of how RuboCop gets used, and I think we’re only getting
started on adapting to that. Next on my list is --changed-lines, so an agent (or a
person) can focus on the offenses in the lines it actually changed. If you’re running
RuboCop through an agent and something about it annoys you, tell us.
One more thing before I go - rubocop.org got completely reworked recently. Most of what it shows now comes straight out of RuboCop itself, there’s an index of every cop, and there’s a playground that runs RuboCop right in your browser, courtesy of ruby.wasm. Go check it out and take the playground for a spin! Feedback on the new design and features is most welcome - just open an issue if something looks off or you’re missing something.
Big thanks to everyone who contributed to this release! Koichi, viralpraxis and Starlexxx carried the bug-fixing once again, and bquorning reported the sandbox crash that got me looking into the rest of them.
That’s all I have for you today. Keep hacking!