RuboCop Ruby linter and formatter

Version 1.92 · source

Start here

rubocop
Lint the project
rubocop -a
Fix safe offenses
rubocop -A
Fix all, incl. unsafe
rubocop <path>
Check files or dirs
rubocop --only <cop>
Run one cop
rubocop -x
Fix layout only
rubocop --auto-gen-config
Write a TODO config
rubocop --init
Create .rubocop.yml

Concepts

  1. Run rubocop reads .rubocop.yml
  2. Autocorrect -a safe, -A unsafe
  3. Fix by hand or disable a cop
  4. Clean exit 0 CI gate

Running

rubocop
Check all Ruby files here
rubocop <path> ...
Check given files or dirs
rubocop -L
List files that would be inspected
rubocop -F
Stop after first file with offenses
rubocop --parallel
Use all CPUs
rubocop -s <path> < <file>
Check stdin as if at path
Used by editor integrations.
rubocop --force-exclusion <path>
Honour Exclude for explicit paths
Needed so editors and pre-commit hooks skip excluded files.
rubocop -c <file>
Use another config file
rubocop -r <lib>
Require a Ruby file or extension
rubocop -v / -V
Show version / full versions
rubocop --ignore-parent-exclusion
Ignore Exclude from parent configs

Choosing cops

rubocop --only <Cop>,<Dept>
Run only these cops or departments
rubocop --except <Cop>
Run all but these
rubocop -l
Lint cops only
rubocop --safe
Skip cops not marked safe
rubocop --show-cops [<Cop>]
Print cops and their settings
rubocop --enable-pending-cops
Turn on pending cops
rubocop --disable-pending-cops
Keep pending cops off
rubocop --only-recognized-file-types
Skip files not matching Include

Autocorrect

rubocop -a
Fix safe offenses
rubocop -A
Fix safe and unsafe offenses
rubocop -x
Fix layout offenses only
rubocop -a --only <Cop>
Fix one cop everywhere
rubocop -A --only Style/<Cop>
Roll out a style change
rubocop -a --disable-uncorrectable
Add todo comments for the rest
Inserts rubocop:todo comments where autocorrect is impossible.
rubocop --fail-level A
Count autocorrected as failures

Output

rubocop -f <name>
Pick an output formatter
rubocop -f simple
Offenses grouped by file
rubocop -f offenses
Count offenses per cop
rubocop -f worst
Files with most offenses
rubocop -f files
Only list offending files
rubocop -f json -o <file>
Machine readable report
rubocop -f github
GitHub Actions annotations
rubocop -f emacs
One line per offense
rubocop -f <name> -f <name2> -o <file>
Several formatters at once
Each -f applies to the -o that follows it.
rubocop -E
Show extra details in messages
rubocop -d
Debug output
rubocop --[no-]color
Force colours on or off
rubocop --fail-level <sev>
Minimum severity that fails
rubocop --display-only-fail-level-offenses
Hide offenses below fail level

Cache and server

rubocop -C false
Disable the result cache
rubocop --cache-root <dir>
Set cache location
rubocop --server
Run via a background server
Reuses a warm process; much faster on repeated runs.
rubocop --start-server / --stop-server
Control the server
rubocop --restart-server
Restart after config change
rubocop --server-status
Show server state
rubocop --no-server
Bypass the server once
rubocop --lsp
Language server for editors

Config files

rubocop --init
Write a starter .rubocop.yml
rubocop --auto-gen-config
Write .rubocop_todo.yml
Also adds inherit_from: .rubocop_todo.yml to .rubocop.yml.
rubocop --regenerate-todo
Redo the TODO file with last options
rubocop --auto-gen-config --exclude-limit <n>
Files listed before cop is disabled
Default 15.
rubocop --auto-gen-only-exclude
Only Exclude, never Max
rubocop --no-auto-gen-timestamp
Stable diffs of the TODO file
rubocop --no-offense-counts
Omit counts in the TODO file
RUBOCOP_OPTS="<flags>"
Default options from environment
.rubocop
Default CLI options file, one per line

YAML keys

inherit_from: <file>
Include other configs
inherit_gem: { <gem>: <file> }
Use a config shipped in a gem
plugins: - <name>
Load extension plugins
Newer extensions such as rubocop-rails use plugins; older style uses require.
require: - <lib>
Load extension by require
AllCops: NewCops: enable
Opt into pending cops
AllCops: TargetRubyVersion: <x.y>
Set Ruby version to parse as
AllCops: Exclude: - <glob>
Skip paths everywhere
AllCops: SuggestExtensions: false
Silence extension hints
<Dept>/<Cop>: Enabled: false
Disable a cop
<Dept>/<Cop>: Exclude: - <glob>
Skip paths for one cop
<Dept>/<Cop>: Max: <n>
Tune a numeric limit
<Dept>/<Cop>: Severity: <level>
Change severity of a cop
<Dept>: Enabled: false
Disable a whole department
AllCops: FailLevel: <sev>
Config form of --fail-level

Inline comments

# rubocop:disable <Cop>
Turn off from here
# rubocop:enable <Cop>
Turn back on
<code> # rubocop:disable <Cop>
Disable for one line
# rubocop:disable <Cop1>, <Cop2>
Several cops at once
# rubocop:disable <Dept>
Whole department
# rubocop:disable all
Every cop
# rubocop:todo <Cop>
Disable, marked as debt
# rubocop:disable <Cop> -- <reason>
Add an explanation

Recipes

Adopt on an old codebase
rubocop --auto-gen-configrubocop -arubocop -f offenses# then delete TODO entries as you fix them
Roll out one cop safely
rubocop --only Style/<Cop> -f offensesrubocop -a --only Style/<Cop>git diff --stat
CI gate with annotations
bundle exec rubocop --parallel -f github# non-zero exit fails the job
Lint only changed files
git diff --name-only --diff-filter=d origin/main -- '*.rb' \  | xargs rubocop --force-exclusion