Review of Ruby Static Analysis Tools

In this article:
Subscribe to our blog:

Having trouble deciding which tool to use for Ruby static analysis, or perhaps unsure whether you found the most common ones? Here’s a small list that may be helpful.

This review was first written in 2015 and was updated in October 2026. The original three tools are all still actively maintained, but they have changed quite a bit, and a few newer tools (Standard, bundler-audit, and the Sorbet and Steep type checkers) have earned a place on the list.

1: RuboCop

RuboCop logo

Right out of the box, RuboCop enforces many of the guidelines outlined in the community Ruby Style Guide and, not only does it find problems for you, it can fix many of them automatically. It works both as a linter and as a code formatter.

The checks RuboCop performs are called cops, and they are grouped into departments. Core RuboCop ships more than 600 cops in departments such as Style, Layout, Lint, Metrics, Naming and Security, plus Bundler and Gemspec cops for your dependency files.

Rails cops are no longer part of the main gem: they were extracted into rubocop-rails, and performance cops into rubocop-performance. There are also official plugins for RSpec, Minitest and more, and you can write your own cops. Since RuboCop 1.72, the recommended way to load extensions is the plugins key:

# Gemfile
group :development do
  gem "rubocop", require: false
  gem "rubocop-rails", require: false
  gem "rubocop-performance", require: false
end
# .rubocop.yml
plugins:
  - rubocop-rails
  - rubocop-performance

Cops detect offenses. With the following sample code:

# frozen_string_literal: true

def camelMethod
   puts "This line has 3 spaces indentation"
end

RuboCop’s offense report looks like this:

Inspecting 1 file
C

Offenses:

code.rb:3:5: C: Naming/MethodName: Use snake_case for method names.
def camelMethod
    ^^^^^^^^^^^
code.rb:4:1: C: [Correctable] Layout/IndentationWidth: Use 2 (not 3) spaces for indentation.
   puts "This line has 3 spaces indentation"
^^^
code.rb:4:9: C: [Correctable] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols.
   puts "This line has 3 spaces indentation"
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1 file inspected, 3 offenses detected, 2 offenses autocorrectable

(The magic comment on the first line is there because, by default, RuboCop also flags files that don’t have it.)

Autocorrection comes in two strengths: rubocop -a applies only safe corrections, while rubocop -A also applies unsafe ones that may change behavior. On an existing codebase, rubocop --auto-gen-config writes a .rubocop_todo.yml that disables current offenses, so you can start from a clean run and fix things gradually.

You can enable or disable specific cops and alter their behaviour, including their severity. There are six severity levels: info, refactor, convention, warning, error and fatal.

There’s also a cache mechanism, enabled by default, so files that haven’t changed don’t need to be inspected again on large projects.

RuboCop integrates with editors through its built-in language server (rubocop --lsp, available since 1.53), and there is an official VS Code extension.

2: Standard

Standard Ruby brings the approach of StandardJS to Ruby. It’s a linter and formatter built on RuboCop that ships a fixed, “unconfigurable” configuration for RuboCop’s built-in cops and those in rubocop-performance. You can’t change the rules, but you can still ignore files or individual lines, set the oldest Ruby version you support, and add plugins such as standard-rails.

# Gemfile
gem "standard"
bundle exec standardrb        # report offenses
bundle exec standardrb --fix  # apply safe fixes
# .standard.yml (optional)
plugins:
  - standard-rails

Standard also includes a language server (standardrb --lsp) and a Ruby LSP add-on for editor integration.

3: Reek

Reek logo

Reek detects code smells. Bad smells are symptoms that may (but not necessarily do) indicate a deeper design problem.

Reek includes checks for Control Couple, Data Clump, Feature Envy, Large Class, Long Parameter List, Nested Iterators, Simulated Polymorphism, Too Many Statements, Uncommunicative Name, Unused Parameters, Utility Function and more (see Code Smells for the full list).

Given this file:

# Builds greetings for a user.
class Greeter
  def initialize(name)
    @name = name
  end

  def sayHello
    "Hello, #{@name}"
  end
end

Here’s Reek’s output:

$ reek --no-documentation greeter.rb
Inspecting 1 file(s):
S

greeter.rb -- 1 warning:
  [7]:UncommunicativeMethodName: Greeter#sayHello has the name 'sayHello'

Without --no-documentation, each warning also links to the documentation for that smell.

The configuration is based on a .reek.yml file in the project directory (running reek --todo lib/ once generates one that silences all existing warnings, so you can adopt Reek gradually). Specific smells can be suppressed for specific methods or classes with source code comments, and many smells only trigger once a threshold is reached.

It does make sense; if you had a bowl of cooked rice you wouldn’t say the dish smelled bad because of one roasted grain, but if you had too many of those that would probably spark a smell alert. Similarly, an instance wouldn’t smell, but you could set up a limit to how many would.

Every smell has some basic options that allow you to enable detection or exclude parts of the project, and configuration can be set per directory, which is handy in Rails apps where controllers and helpers deserve different rules.

4: Brakeman

Brakeman logo

I’m including Brakeman on the list even though it is a very different tool than the other ones here, but there’s a reason for this.

Brakeman is a static analysis security scanner for Ruby on Rails applications; however, it runs on code, not on the website itself, meaning that you don’t need to set up your web server to run the tool, and you can start using it from day one, just as you’re writing your first lines of code. It supports applications from Rails 2.3 up to Rails 8.x.

This tool will catch many known vulnerabilities such as SQL Injection and Cross Site Scripting (those are three different links, BTW), but the list goes on.

Since it parses the code itself, Brakeman will not catch problems related to the database or the web server itself but, on the other hand, the tool is capable of finding problems before they become exploitable.

# Gemfile
group :development do
  gem "brakeman", require: false
end
bundle exec brakeman                   # run from the Rails application root
bundle exec brakeman -o brakeman.html  # write an HTML report
bundle exec brakeman -I                # interactively manage config/brakeman.ignore

Each warning gets a confidence level: high, medium or weak. Reports can be written as text, HTML, JSON, SARIF, JUnit, Markdown, CSV and several other formats, and by default Brakeman exits with a non-zero status when it finds warnings, which makes it easy to fail a CI build. Jenkins users can collect results with the Warnings Next Generation plugin. Since Rails 7.2, newly generated Rails applications include Brakeman and run it in their default GitHub CI workflow.

One thing to be aware of: Brakeman is distributed under the Brakeman Public Use License. Using it to analyze your own software is free, but commercial uses such as offering it as part of a paid product or service require a commercial license.

5: bundler-audit

Brakeman looks at your code; bundler-audit looks at your dependencies. It checks your Gemfile.lock against the Ruby Advisory Database for gem versions with known vulnerabilities, flags insecure gem sources (http:// and git://), and lets you ignore advisories you have already worked around.

# Gemfile
group :development do
  gem "bundler-audit", require: false
end
bundle exec bundle-audit check --update  # update the advisory database, then audit Gemfile.lock

Since Rails 8.1, new Rails applications include bundler-audit by default, with a bin/bundler-audit script and a config/bundler-audit.yml file for ignored advisories.

6: Sorbet

Sorbet is a fast, gradual type checker for Ruby, built at Stripe. You opt files in with a # typed: sigil, from false (syntax, constants and signatures only) through true (type errors) to strict (every method needs a signature), and add signatures over time. The getting started guide uses Tapioca to generate type definitions (RBI files) for your gems:

# Gemfile
gem "sorbet", group: :development
gem "sorbet-runtime"
gem "tapioca", require: false, group: [:development, :test]
bundle exec tapioca init  # set up the sorbet/ directory and generate RBI files
bundle exec srb tc        # type check the project

Signatures are written in Ruby itself, and sorbet-runtime can also check them while your code runs:

# typed: true
require "sorbet-runtime"

class Greeter
  extend T::Sig

  sig { params(name: String).void }
  def initialize(name)
    @name = name
  end

  sig { returns(String) }
  def say_hello
    "Hello, #{@name}"
  end
end

Sorbet’s language server provides editor features such as autocompletion and go-to-definition. Note that, according to its FAQ, the static checker runs on macOS and Linux but not on Windows.

7: Steep

Steep takes a different approach to type checking. It uses RBS, the type signature language that ships with Ruby as a bundled gem, and types are declared in separate .rbs files, usually under sig/. Steep doesn’t infer types from your Ruby code, so you declare them first:

# sig/greeter.rbs
class Greeter
  @name: String

  def initialize: (String name) -> void
  def say_hello: () -> String
end
gem install steep
steep init   # generate a Steepfile, then list your code and signature directories in it
steep check  # type check

Signatures for third-party gems can be installed with rbs collection, and editors can use Steep through its language server (steep langserver).

Which one should I use?

As with any other list of tools, it boils down to a matter of personal choice, although for some scenarios there are some clear winners. Most of these tools are complementary rather than alternatives to each other:

  • Style and formatting: RuboCop if you want full control over the rules; Standard if you’d rather not configure anything. New Rails applications (since Rails 7.2) already come with RuboCop and the rubocop-rails-omakase rule set.
  • Design problems: Reek, if you’re looking for signs of potential problems in how your classes and methods are structured.
  • Security of your Rails code: Brakeman.
  • Vulnerable dependencies: bundler-audit.
  • Type checking: Sorbet if you want signatures written inline in Ruby (and optional runtime checks); Steep if you prefer RBS, Ruby’s own signature format, kept in separate files.

All of them can run locally, in a pre-commit hook or in CI.

Also, if you’re looking for a simple and time-saving way to run these kinds of checks centrally on every commit and pull request, you should definitely try Codacy. Codacy runs RuboCop, Reek and Brakeman for Ruby and picks up existing .rubocop.yml and config/brakeman.yml files (its documentation notes that, due to licensing, it doesn’t support the latest Brakeman version). Codacy also allows you to monitor issues over time and see the impact each commit has on your code base (new issues and fixed issues). It’s a great way to make sure your code is safe and sound and also an awesome tool to bring one up to speed with a language’s best practices.

Conclusion

There are several Ruby static analysis tools, each of them with their own strengths (and many of them are complementary, not just alternatives to each other).

In fact, there are quite a few missing from this list, and some of them may be quite relevant to what you’re doing.

I would also recommend checking out Flay (finds structurally duplicated code), Flog (scores how complex, or “tortured”, your methods are), Rails Best Practices (code metrics for Rails apps, available as the rails_best_practices gem) and RubyCritic, which wraps Reek, Flay and Flog into a single quality report. All of them still receive updates.

If there’s any other you think deserves a mention, please let me know in the comments.

Subscribe to our blog

Stay updated with our monthly newsletter.