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=N caps how many offenses each cop reports. A legacy codebase can easily have thousands of Style/StringLiterals offenses, and an agent doesn’t need to read all of them to get the idea.
  • --explain COP prints 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-cops and --show-docs-url now 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_inspection answers in the same shape as --format json instead 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_explain tool does what --explain does.
  • Inspection and autocorrection take only, except and changed, so an agent can check just the files it touched, or just Lint.
  • 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, like Lint/UselessAssignment, are held back by default, since the code is probably mid-edit. An agent that’s done editing can ask for them with contextual: 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/UselessAssignment now catches a variable that a block keeps assigning but nothing ever reads.
  • Security/JSONLoad now reports JSON.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/NegativeArrayIndex is now marked as unsafe.
  • --changed, --diff and the SARIF formatter, all new in 1.91, got a round of fixes.
  • RuboCop no longer loads net/http on every run, only when it fetches a remote config.
  • regexp_parser 2.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!