rrubocop 0.8.14

10x faster RuboCop drop-in. Same output format and configs, without maintaining RuboCop gems.
docs.rs failed to build rrubocop-0.8.14
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: rrubocop-0.8.13

rrubocop

10x faster RuboCop drop-in — same CLI, .rubocop.yml, and offense output, without maintaining RuboCop gems. Linting and simple config need no Ruby; complex ERB still does. Point it at an existing project and use it like RuboCop.

One binary — runs the same way regardless of rbenv, rvm, system Ruby, or Docker. Uses tree-sitter; no Ruby runtime required for linting or simple ERB. Unsupported ERB falls back to ruby / bundle exec ruby.

Drop-in parity: reads your existing .rubocop.yml, emits RuboCop-like text/JSON, supports -a/-A autocorrect, and grows cop coverage over time.

Baseline (shown in --help / --version): rubocop 1.91.0 with rubocop-rails 2.37.0, rubocop-performance 1.27.0, rubocop-rspec 3.9.0, rubocop-rspec_rails 2.32.0, rubocop-factory_bot 2.28.0 — pinned in src/resources/baseline.json.

Parity runs have been verified over 600+ installed Ruby gem projects (RuboCop vs rrubocop on the same trees).

Install

brew install adrianov/rrubocop/rrubocop
cargo install rrubocop

macOS (.tar.gz from GitHub Releases; binary + man):

# Apple Silicon — use the *-x86_64-apple-darwin.tar.gz asset on Intel Macs
curl -LO https://github.com/adrianov/rrubocop/releases/download/v0.8.14/rrubocop-0.8.14-aarch64-apple-darwin.tar.gz
tar -xzf rrubocop-0.8.14-aarch64-apple-darwin.tar.gz
sudo cp rrubocop-0.8.14-aarch64-apple-darwin/rrubocop /usr/local/bin/
sudo mkdir -p /usr/local/share/man/man1
sudo cp rrubocop-0.8.14-aarch64-apple-darwin/rrubocop.1 /usr/local/share/man/man1/

Ubuntu / Debian (.deb from GitHub Releases; amd64, Ubuntu 22.04+ / Debian bookworm+):

# example for v0.8.14 — use the asset name from the release page
curl -LO https://github.com/adrianov/rrubocop/releases/download/v0.8.14/rrubocop_0.8.14-1_amd64.deb
sudo dpkg -i rrubocop_0.8.14-1_amd64.deb
man rrubocop
rrubocop [OPTIONS] [PATH]...

Features

  • Config — RuboCop-compatible resolution: walk-up discovery, inherit_from / inherit_gem / require/plugins, inherit_mode (merge/override), nested .rubocop.yml overrides, DisabledByDefault, NewCops / Enabled: pending, plus per-cop Enabled / Exclude / Include / options; public gem defaults/inherit_gem YAML are vendored by version (from Gemfile.lock, with same_as aliases when YAML is identical) and parsed in memory; private/unlisted gems fall back to bundle info --path; simple ERB in YAML expands natively (Ruby only for unsupported tags)
  • Autocorrect — -a (safe) / -A (all)
  • Output — progress (marks stream as files finish), text, json, github, quiet, files, … (TTY color like RuboCop; --color / --no-color)
  • Directives — # rubocop:disable / enable
  • Parser — tree-sitter-ruby (no Prism / no CRuby)
  • Cache — content-addressed cache.redb under $RRUBOCOP_CACHE_DIR or $XDG_CACHE_HOME/rrubocop / ~/.cache/rrubocop (same style as abcop); --cache false skips reads but still writes
  • Prefer MCP with LLMs. rrubocop --mcp is the best way to use rrubocop from an agent: the model gets offenses as soon as it writes, so it can fix and autocorrect in the same turn and ship effective code right away — not after a later CLI/CI pass. Official Rust rmcp SDK; same tools as RuboCop 1.85+: rubocop_inspection and rubocop_autocorrection

Reference implementations: nitrocop (architecture & fixtures), upstream RuboCop.

Built-in cops

Departments grow breadth-first from common RuboCop plugin sets (nitrocop / gem sources). Notable coverage:

Department Notes
Layout/* 90 layout cops (alignment, spacing, empty lines, indentation; all with autocorrect)
Lint/*, Style/*, Naming/*, Security/* 69 / 143 / 9 / 4
Metrics/* AbcSize, BlockNesting, ClassLength, CollectionLiteralLength, ModuleLength, ParameterLists
Rails/* 62 rails cops
Performance/* 24 performance cops
RSpec/* 104 rspec cops
RSpecRails/* 2 (HttpStatus, InferredSpecType)
FactoryBot/* 4 (AssociationStyle, AttributeDefinedStatically, CreateList, FactoryClassName)
Bundler/*, Gemspec/*, Rake/* 4 / 4 / 5
GraphQL/* 26 rubocop-graphql cops

Use rrubocop --list-cops for the full registered set, and rrubocop --list-autocorrectable-cops for cops with -a/-A support (180 with autocorrect so far; Layout complete; Style/Lint/Rails/RSpec growing).

Usage

rrubocop                         # lint .
rrubocop app lib                 # paths
rrubocop -f json .               # JSON offenses
rrubocop -a .                    # safe autocorrect
rrubocop -A .                    # all autocorrect
rrubocop --only Metrics/AbcSize lib
rrubocop --rubocop-version 1.79.2 . # emulate a project's pinned RuboCop (matches CI's bundled gem)
rrubocop --list-cops
rrubocop -L                      # list target files
rrubocop -F 10                   # stop after 10 offenses (off by default; `-F` = 1)
                                 # with `-a`/`-A`, N is non-autocorrectable offenses only
rrubocop --mcp                   # MCP server on stdio (for AI clients)

Exit codes: 0 clean, 1 offenses at/above --fail-level, 2 error.

MCP (Model Context Protocol)

Preferred for LLM / agent workflows. Wire rrubocop as an MCP server so the model can call rubocop_inspection / rubocop_autocorrection while it edits: feedback arrives in the same turn, the agent corrects soon, and it writes clean code on the first pass instead of discovering offenses only in CI.

rrubocop --mcp runs a long-lived MCP server on stdio — same idea as RuboCop’s MCP, with no Ruby mcp gem. Tools:

Tool Purpose
rubocop_inspection Lint via path / paths (string or array; required for filesystem inspect) and/or inline source_code; returns LSP-shaped offense JSON
rubocop_autocorrection Same targets as inspection; safety: true = safe only; writes files when a filesystem path is set

Always pass path or paths (absolute file or directory preferred; path may be a string or an array). The server walks up from the first target to find .rubocop.yml. Omitting targets for filesystem ops errors out (avoids scanning $HOME when MCP cwd is mis-set). Files without a recognized Ruby extension, filename, or shebang (e.g. YAML/JSON configs) are silently skipped — same as upstream MCP, whose TargetFinder runs in :only_recognized_file_types mode — so passing mixed paths yields no Lint/Syntax noise; summary.target_file_count reflects inspected files only. A long-lived global MCP started from $HOME otherwise inherits ~/.rubocop.yml (AllCops: Enabled: false is common) and misses project cops such as RSpec/ExampleLength.

  • MCP Registry name: mcp-name: io.github.adrianov/rrubocop

Metadata lives in server.json (Cargo package on crates.io). Each v* tag publishes that listing to the MCP Registry.

Example client config (Cursor / VS Code / Windsurf):

{
  "mcpServers": {
    "rrubocop": {
      "type": "stdio",
      "command": "rrubocop",
      "args": ["--mcp"],
      "cwd": "/path/to/your/project"
    }
  }
}

Claude Code:

claude mcp add rrubocop -- rrubocop --mcp

Intended for MCP clients, not interactive use.

Caching

Content-addressed cache under $RRUBOCOP_CACHE_DIR (or $XDG_CACHE_HOME/rrubocop / ~/.cache/rrubocop). Keys cover contents, version, rule revision, --only/--except, --rubocop-version, config fingerprint, and path. Auto-pruned to 20 000 entries; --cache false skips reads but still writes. Autocorrect runs bypass the cache. Nothing is written inside the project.

Benchmarks

Cold lint (cache off) on a large Rails codebase (~3.8k Ruby files), same host:

Tool Wall clock Result Notes
bundle exec rubocop --cache false 2m 37s (2:36.64) 0 offenses ~99% CPU (mostly single-core)
rrubocop --cache false 7.0s (7.005) 0 offenses ~1040% CPU (parallel)
nitrocop --no-cache 8.9s (8.906) ~21k offenses ~1000% CPU; not a fair parity run (see below)

rrubocop is ≈ 22× faster wall clock than RuboCop (156.6s / 7.0s) on the same clean result. RuboCop user time was 155s; rrubocop used 71s of CPU across cores.

nitrocop caveat: out of the box it did not honor the same disabled cops / custom rules / gem configs as bundle exec rubocop (e.g. failed inherit_gem load, skipped/unimplemented cops), so it reported ~21k false positives vs RuboCop/rrubocop’s clean run. Matching that baseline needs extra setup (--migrate, plugin/config wiring). Treat the 8.9s figure as raw throughput only, not drop-in parity.

Cold lint (cache off) on rails/rails (main, RuboCop 1.79.2 via bundle exec), same host (4 cores), both clean (0 offenses). Two runs averaged:

Tool Wall clock Notes
bundle exec rubocop --cache false 1m 7s (67.254) ~99% CPU (mostly single-core); 3543 files
rrubocop --cache false 5.7s (5.668) ~357% CPU (parallel); 3446 files

≈ 12× faster wall clock (67.254s / 5.668s). RuboCop user time was 66.9s; rrubocop used 20.2s of CPU across cores.

Same host, cold --cache false, offense-set parity on Active Support and Active Record (fp=0, fn=0 on shared .rb files):

Target RuboCop rrubocop Speedup
activesupport (rails main) 11.566s (531 files) 1.872s ≈6.2×
activerecord (rails main) 29.611s (1162 files) 2.780s ≈10.7×
activesupport (v8.1.3.1) 10.729s (506 files) 1.795s ≈6.0×
activerecord (v8.1.3.1) 27.847s (1126 files) 2.656s ≈10.5×

Cold lint on a fresh rails new app (Rails 8.1.3.1, default rubocop-rails-omakase via inherit_gem, RuboCop 1.90.0 via bundle exec), plus scaffold/model/mailer/job generators (41 identical target files). Offense-set parity fp=0, fn=0 (both clean). Two-run average:

Tool Wall clock
bundle exec rubocop --cache false 0.722s
rrubocop --cache false 0.593s

Cross-test vs nitrocop

With a local nitrocop build:

testdata/cross_test_nitrocop.py /path/to/fixture_dir

Compares (path, line, cop_name) offense sets.

License

GPL-3.0-or-later. See NOTICE for MIT attribution of nitrocop-derived design/logic.