CLI tool
rubocop/rubocop-rspec avatar
rubocop/rubocop-rspec

rubocop-rspec adds RSpec aware cops to RuboCop, and loading it is the whole trick

Code style checking for RSpec files.

859 stars300 forksRubyMIT

At a glance

What is it?
An MIT licensed RuboCop extension whose value is a set of RSpec specific cops, but where most of the setup friction sits in telling RuboCop to load the plugin at all.
Who is it for?
Adopt rubocop-rspec if your Ruby project has a substantial RSpec suite and wants the same style rules and .rubocop.yml treatment applied to spec files. Skip it if you have few specs or want a single opinionated formatter for the whole codebase, since the alternative is a plain RuboCop setup with no RSpec layer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The extension exists because generic RuboCop rules do not know what an example group is

rubocop-rspec is an extension for RuboCop that adds RSpec specific analysis to a Ruby project. The project description is as narrow as the name: code style checking for RSpec files. It is not a test runner, not a replacement for RSpec itself, and it does not execute your suite. It reads spec files and reports style problems the way RuboCop reports style problems anywhere else.

The gap it fills is specific. RuboCop's standard cops are written against plain Ruby. A spec file is full of constructs that read oddly to a generic rule set: blocks passed to describe and it, subjects defined with let, expectations chained onto matchers. Without RSpec aware rules, a project either writes those constructs differently to satisfy the linter, or it excludes spec files from linting entirely. Both outcomes push the decision onto style, and this extension removes it by teaching the linter the vocabulary.

Because it is an extension rather than a fork, the division of labour stays clean. RuboCop keeps the parser, the reporting and the configuration engine; this project adds cops and makes sure they are loaded. The repository reflects that: lib/ holds the code, config/ holds the default configuration, and the cops live under lib/rubocop/cop/rspec, where each one carries its own examples and documentation.

The audience is Ruby teams whose spec files are a large share of the codebase, which is typical for services built on Rails-style testing practices. A project with a handful of specs gains little from it.

Loading the extension takes three routes and the config file is the one that scales

Before any cop fires, RuboCop has to know the extension exists. The documentation lists three ways to do that, and the difference between them is where the real work lies.

The first route is the RuboCop configuration file. In .rubocop.yml you name the plugin directly.

yaml
plugins: rubocop-rspec

If you already load other extensions, the array notation keeps them together.

yaml
plugins:
  - rubocop-other-extension
  - rubocop-rspec

Once the file is in place, running rubocop loads the RSpec cops alongside the standard cops with no extra flag on every invocation. This is the route that scales, because it applies to every developer, every CI job and every editor that shells out to RuboCop.

The second route is the command line, for a one-off run.

bash
rubocop --plugin rubocop-rspec

The third route is a Rake task, which is what teams that drive everything through Rake tend to reach for.

ruby
RuboCop::RakeTask.new do |task|
  task.plugins << 'rubocop-rspec'
end

Note that each route uses a different mechanism and a different key. The config file uses plugins, the CLI uses --plugin, and the Rake task pushes onto task.plugins. Mixing them up produces a silent failure, since an unloaded extension simply means no RSpec cops are reported and the run still exits successfully.

The plugins key needs RuboCop 1.72 or newer, older releases want require

The documentation attaches a version constraint to the config file route. The plugin system is supported in RuboCop 1.72+, and in earlier versions you use require instead of plugins. That single sentence covers the most common upgrade surprise in this project, because the config file syntax changed while the extension itself kept working.

The practical failure mode is quiet. A project that upgrades RuboCop and keeps its old require-based configuration still lints, but nothing reports on the extension, and the team may believe the cops are running when they are not. A project that moves to plugins on an older RuboCop gets a configuration error instead, which is at least visible.

Versioning also has to line up on the extension side. The current line is 3.10.x, with v3.10.2 published on 2026-06-06 after v3.10.1 and v3.10.0 on 2026-06-05. Two upgrade guides are published, one for v3.x and one for v2.x, and the documentation sends you to the right one depending on where you are starting. Moving from a v2.x install to the current line is therefore a documented step with its own document, not a matter of bumping a version number.

If your project is still on a v2.x configuration, read the v3.x upgrade guide before you change anything, because the cop behaviour and configuration keys around them are what that document covers.

Cops are configured like any other, with Exclude lists for legacy files

The documentation is explicit that RSpec cops behave like every other RuboCop cop in your .rubocop.yml. The difference is that they carry the RSpec/ namespace, so a rule such as RSpec/SpecFilePathFormat is configured the same way as a standard cop.

yaml
RSpec/SpecFilePathFormat:
  Exclude:
    - spec/my_poorly_named_spec_file.rb

That example is the important one for anyone introducing the extension to an existing suite. The cops encode one house style, and a codebase written before the extension existed will not match it. The Exclude list is the escape hatch that lets a team adopt the extension without rewriting hundreds of existing spec files on day one. The same mechanism applies per cop and per directory.

Two related pieces of the repository layout matter here. The root carries both .rubocop.yml and .rubocop_todo.yml, the second being the conventional place to record offenses that are knowingly not fixed yet. The docs/ directory holds the per-cop documentation, and each cop in lib/rubocop/cop/rspec ships with its own examples. The config/ directory carries the default configuration for the cops, which is where the defaults can be inspected before you override them.

The trade-off is worth stating plainly. Because every cop is individually configurable and individually excludable, a project can end up with a configuration where the RSpec layer technically runs but almost nothing is enforced. The extension does not warn you about that, and it is the most likely reason a team believes it has adopted RSpec style checks when it has not.

The Rake task and the CLI leave a gap that CI can walk into

The three loading routes are not equivalent in what they guarantee. A .rubocop.yml entry applies to every invocation of rubocop from that directory, including the ones your editor plugin makes and the ones CI makes. The --plugin flag applies only to the command you typed. The Rake task applies only to the tasks that go through Rake.

That gap is where failures happen in practice. A team that adds the Rake task, because their build is driven by rake, and never touches .rubocop.yml gets a lint pass on the Rake path and no RSpec cops on the direct command line. Someone running rubocop locally from an editor sees a clean file. CI, running the same Rake task, sees the offenses. The divergence is invisible from either side alone.

The same trap applies in reverse. A configuration that lists rubocop-rspec under plugins makes the CLI and the Rake task redundant, so teams that pick the config route can delete the other two and end up with one source of truth.

A related detail is the require: false setting recommended for the Gemfile entry.

ruby
gem 'rubocop-rspec', require: false

Without it, Bundler would load the gem into the application process on every boot, which is not what you want for a development-time linter. Keeping it out of the load path also keeps the extension from affecting anything other than RuboCop runs, which matters for a gem that ends up in the same bundle as your app.

MIT licensed, small dependency surface, and a release cadence you can plan around

rubocop-rspec is MIT licensed, with the full text in the MIT-LICENSE.md file at the repository root. That is a permissive licence with no obligation to publish changes, so a company can vendor it internally without a separate agreement, and derived work can be kept under the same terms. That is a statement about the licence text, not legal advice, and teams with their own review process still need to apply it.

The dependency surface is small by design. The gem is a plugin for RuboCop rather than a framework, so it sits beside RuboCop in a development group of the Gemfile and is never loaded by application code. The repository has no separate service, no database and no daemon. What you add to a project is a gem, a config file and a set of cops.

On maintenance, the repository is not archived and the last push was on 2026-10-14. The recent release list shows three tags in quick succession on 2026-06-05 and 2026-06-06, at v3.10.0, v3.10.1 and v3.10.2. Two patch releases on consecutive days suggests a habit of shipping corrections as they are found, which means the version you pin should be one you have actually run against your suite rather than the newest one available.

The remaining upgrade work is a configuration problem, not a code problem. RuboCop itself evolves its own cops, and this extension's cops evolve with it, so a RuboCop major upgrade can surface new offenses in spec files that the project has never linted that way before. The .rubocop_todo.yml file at the repository root is the pattern to follow, recording what is not fixed yet so the run stays green while the debt is visible.

Editorial conclusion

Adopt rubocop-rspec if your Ruby project has a substantial RSpec suite and wants the same style rules and .rubocop.yml treatment applied to spec files. Skip it if you have few specs or want a single opinionated formatter for the whole codebase, since the alternative is a plain RuboCop setup with no RSpec layer. Verify first that your RuboCop version is 1.72 or newer if you plan to use the plugins key, since older releases need require instead, and read the upgrade guide for v3.x because the current 3.10.x line changed configuration behaviour. Decide explicitly which of the three loading routes you adopt, and put it in .rubocop.yml rather than in a personal command line, so every contributor and CI run uses the same cop set.

Frequently asked questions

How do I install rubocop-rspec for my Ruby project?

Install the gem with gem install rubocop-rspec, or add gem 'rubocop-rspec', require: false to your Gemfile when you use bundler. The gem is an extension to RuboCop, so RuboCop has to be present as well.

How do I make RuboCop load the RSpec cops?

Add plugins: rubocop-rspec to your .rubocop.yml, pass --plugin rubocop-rspec on the command line, or push 'rubocop-rspec' onto task.plugins in a RuboCop::RakeTask. The plugin system needs RuboCop 1.72+, and earlier versions use require instead.

Can I exclude existing spec files from the new RSpec cops?

Yes. The cops are configured like any other RuboCop cop, so an Exclude list under a cop name such as RSpec/SpecFilePathFormat lets you leave legacy files out while the rules apply to new work.

What changed when I upgraded to rubocop-rspec v3?

The project publishes a separate upgrade guide for v3.x and another for v2.x, and the documentation points you to the matching one. Moving from a v2.x install to the current 3.10.x line is a documented configuration step rather than a version bump, so read the v3.x guide before changing your setup.

What license does rubocop-rspec use?

It is MIT licensed, with the full text in the MIT-LICENSE.md file in the repository root. Since the extension runs only as a development-time linter, it never reaches the code you ship.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. rubocop/rubocop-rspec on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rubocop-rubocop-rspec.svg)](https://hysenlabs.com/projects/rubocop-rubocop-rspec)

Was this useful?