Community/Tools

Ruff: replacing Flake8, isort and Black with one fast linter and formatter

How to set up Ruff as both linter and formatter, which rule sets are worth enabling, and how to roll it out on an existing codebase without a giant noisy diff.

Author's connection to this tool: No connection. An independent overview written by the RecallRun editors.

Many Python projects run three or four tools on every commit: Flake8 and its plugins for linting, isort for imports, Black for formatting, maybe pyupgrade. Ruff, from Astral, implements most of those checks in one Rust binary and runs them fast enough that linting a large codebase feels instant.

Install and run

pip install ruff       # or: uv add --dev ruff
ruff check .           # lint
ruff check . --fix     # apply safe automatic fixes
ruff format .          # format code (Black-compatible style)

Configure in pyproject.toml

Keep the configuration next to the rest of your project settings:

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = [
  "E", "F",   # pycodestyle errors and Pyflakes (the classic Flake8 core)
  "I",        # import sorting (isort)
  "B",        # flake8-bugbear: likely bugs and design problems
  "UP",       # pyupgrade: modern syntax for your Python version
  "SIM",      # simplifications
]
ignore = ["E501"]   # let the formatter handle line length

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["B011"]

A sensible path is to start with E, F and I, then add B and UP, which catch real bugs such as mutable default arguments and outdated syntax. Ruff supports hundreds of rules; resist enabling everything at once.

What it catches that matters

A few examples of issues these rule sets flag:

def add_item(item, items=[]):     # B006: mutable default argument
    items.append(item)
    return items

import os, sys                    # E401 / I001: multiple imports, unsorted
from typing import List

def names(xs: List[str]) -> List[str]:   # UP006: use list[str] on modern Python
    return [x for x in xs if x != None]  # E711: comparison to None

ruff check --fix resolves many of these automatically; the rest come with a clear message and rule code you can look up.

Use it in your editor and pre-commit

Most editors have a Ruff extension that lints and formats on save. For pre-commit:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.9          # pin to the version your team uses
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

And in CI, fail the build on lint errors or unformatted files:

ruff check .
ruff format --check .

Rolling it out on an existing codebase

Turning on a new linter across a large project can produce thousands of warnings. A calmer approach:

  1. Format first, in one commit. Run ruff format . and commit it alone, so later diffs stay readable. Add that commit's hash to .git-blame-ignore-revs so git blame skips it.
  2. Enable a small rule set (E, F, I) and fix or auto-fix everything.
  3. Add rule groups one at a time, each in its own pull request.
  4. For legacy noise you can't fix yet, use per-file ignores, or Ruff's option to add noqa comments to existing violations, so new code is held to the full standard while old code is cleaned up gradually.

Where Ruff doesn't replace other tools

Ruff is a linter and formatter, not a type checker. Keep mypy or Pyright for type checking. Some niche Flake8 plugins may not have Ruff equivalents yet, so check the rule list for anything your team depends on.

Verdict

Ruff gives most teams the same checks they already run with less configuration, one dependency and much faster feedback, which matters most in pre-commit hooks where slow tools get skipped. For a new project it's an obvious default; for an existing one, the gradual rollout above takes an afternoon.

Written by

RecallRun Editors

Practical guides and independent tool overviews from the RecallRun team. Every post is written to be tested on your own machine.

Website

Written by RecallRun Editors for the RecallRun community. Community posts are checked for safety and reviewed by our editors before publishing, but the views and claims are the author's own. Links are the author's; open them with care. Report this post.

More from the community

Write for RecallRun

Share a tech article or a tool you built. Every post is checked and reviewed before it goes live.

Start writing