mrkeyoor.com_
Wed 12 Aug 16:49 UTC
Dev Toolsevaluationupdated 12 Aug 2026

ruff

Ruff is a very fast Python linter and formatter written in Rust. It replaces a stack of separate tools for style checks, import sorting, code upgrades, and formatting with one executable that gives developers feedback quickly enough to run on every save and commit.

Verdict

Most modern Python projects should adopt Ruff, first as a linter and then as a formatter if its small style differences are acceptable. Its speed changes code quality checks from a CI chore into immediate feedback, while one configuration can replace several tools. Keep a type checker, retain any unsupported specialist checks, and pin Ruff before upgrading deliberately.

Setup5/5One binary, many installers, useful defaults, and no Rust requirement
Docs5/5Exceptional rule, setting, migration, editor, and behavior references
Community5/5Major adoption with daily issue, pull-request, and release activity
Maturity5/5Widely deployed and disciplined, despite a pre-1.0 version policy

Who it’s for

Python teams that want one fast tool for linting, import sorting, and formatting.
Large repositories where slow hooks and repeated Python startup costs discourage local checks.
Projects using standard Flake8 plugins, Black, isort, pyupgrade, or autoflake behavior that Ruff already implements.
Monorepos that need cascading configuration and consistent editor, pre-commit, and CI behavior.

Who it’s NOT for

Teams dependent on private or third-party Flake8 or Pylint plugins: Ruff does not support custom lint plugins and instead ships rules in its own binary.
Python 2 codebases: the FAQ explicitly says Python 2 is unsupported and type comments from old Python may not be respected.
Projects expecting Ruff alone to replace a type checker or all of Pylint: Ruff's docs say it misses type errors and some inference-based checks those tools catch.
Repositories requiring byte-for-byte Black or isort output: the formatter documents intentional Black deviations, and import sorting differs around aliases, inline comments, and some settings.
Organizations that cannot pin and test tool upgrades: Ruff has no stable API yet, and its version policy permits breaking changes in minor releases before 1.0.

Setup reality

Installation is genuinely easy: use uv, pip, pipx, Homebrew, Conda, or a standalone binary, with no Rust compiler required on common platforms. A greenfield project can run ruff check and ruff format immediately. Migration takes more care because existing Flake8 plugins, Black formatting, isort sections, per-file ignores, target Python versions, and editor settings must be mapped into Ruff's configuration. Start with reporting only, review the diff from fixes and formatting, pin the version in pre-commit and CI, then remove old tools after their outputs agree on the repository.

Python tooling that is fast enough to disappear

Ruff combines a Python linter, formatter, import sorter, and a large catalog of automatic code upgrades in one Rust executable. The project says it implements more than 900 lint rules, including native versions of many popular Flake8 plugins and behavior associated with pyupgrade, pydocstyle, autoflake, and isort. The formatter aims for close compatibility with Black.

The speed claim is central, not decorative. Astral reports Ruff running 10 to 100 times faster than existing Python linters and formatters, with larger improvements in some user reports. Those are project and user measurements rather than a guarantee for every repository. The practical benefit is still easy to understand: a check that returns almost immediately can run in an editor, on every commit, and in CI without becoming the step developers learn to avoid. Built-in caching reduces repeat work further.

The first run is unusually easy

Ruff installs through uv, pip, pipx, Homebrew, Conda, standalone scripts, and other package managers. Common platforms receive prebuilt binaries, so Python users do not need a Rust toolchain. ruff check lints a directory, while ruff format formats it. The two parts are independent, so a team can adopt the linter while keeping Black, or use the formatter without accepting every lint rule.

The defaults are useful without being timid. They catch errors such as unused imports and cover common style, bug-risk, upgrade, and Ruff-specific categories while avoiding stylistic lint rules that fight a formatter. Configuration belongs in pyproject.toml, ruff.toml, or .ruff.toml. Monorepos get hierarchical discovery and cascading configuration, and command-line overrides handle one-off checks. Jupyter notebooks, pre-commit, GitHub Actions, VS Code, and other editors have documented paths.

Automatic fixes deserve a measured rollout. Ruff distinguishes safe fixes from unsafe ones, requiring explicit permission for the latter. That is better than pretending every mechanical rewrite preserves intent. Even safe fixes should first run in a pull request on a mature codebase, particularly when enabling a broad rule family. A fast wrong edit is still wrong.

Consolidation has a boundary

Ruff can replace Flake8 cleanly when a project uses Python 3, Black, and either no plugins or plugins Ruff has reimplemented. It cannot load arbitrary third-party rules. A company with an internal Flake8 checker must retain that runner, upstream the rule, or rewrite its policy around Ruff's built-ins. The same limitation applies to custom Pylint checkers.

Ruff is also not a type checker. Its FAQ recommends using it beside Mypy, Pyright, or Pyre. It can find unused imports and suspicious syntax that a type checker may ignore, but it will not generally prove that an integer was passed where a string was required. Pylint still performs inference-based checks Ruff does not match. Replacing six overlapping style tools is realistic; replacing every form of Python analysis is not.

Legacy projects face another hard stop: Python 2 is unsupported. Ruff targets Python 3 code, and its documentation says old type comments may not be respected. That makes modernization a prerequisite, not a configuration tweak.

Black compatibility is close, not identical

The formatter is designed as a Black replacement and Astral reports more than 99.9 percent identical lines on large projects already formatted by Black. Unformatted code can show more differences, especially around end-of-line comments. Ruff intentionally keeps such comments near their original expressions, ignores pragma comments when measuring line width, formats expressions inside f-strings, and makes different decisions for some nested expressions, multiline strings, and implicit string concatenation.

Import sorting follows a similar pattern. It aims to match isort's Black profile but differs around aliased imports and inline comments, and it does not implement every isort option. These are not reasons to reject Ruff. They are reasons to run both old and new tools against the entire repository before deleting the old configuration. Teams that treat formatting as generated output should expect one reviewed migration diff and then let Ruff own the result.

Preview mode needs restraint. It unlocks unstable rules, fixes, formatter changes, and interfaces, but selecting a preview category can include matching preview rules unless explicit selection is configured. Use it to test upcoming behavior, not as an automatic switch in every production repository.

Versioning and project health

Ruff remains below 1.0 and uses a custom policy: minor versions can contain breaking configuration, stable rule, formatter, file-type, or language-server changes, while patch versions primarily carry fixes and compatible additions. The project says it does not yet have a stable API. Pinning an exact release in pre-commit and CI is therefore sensible, followed by intentional upgrade pull requests.

The maintenance signal is excellent. The repository was pushed on August 12, 2026, five days after release 0.16.2 was published. That patch fixed a false positive and corrected language-server formatting capability registration. Its 2,096 open items combine issues and pull requests, a large queue that reflects both broad scope and intense development. A newly filed nix-shell shebang false positive received a response the same day, while multiple fixes and features were moving through review.

Ruff is mature enough for a default recommendation even with its pre-1.0 label. Adopt it incrementally, preserve specialist tools where the documented boundary demands them, and lock the version. For most Python teams, the simpler configuration and near-instant feedback are worth the small migration cost.

Alternatives

ProjectWhat it isPick it when
Flake8The established Python lint runner with a large third-party plugin ecosystem.pick this instead when custom or unsupported Flake8 plugins are non-negotiable.
BlackThe widely adopted opinionated Python formatter whose style Ruff closely follows.pick this instead when exact Black output and Black's own release behavior matter more than speed or consolidation.
isortA dedicated import sorter with a broader set of import-specific configuration options.pick this instead when your import layout relies on isort behavior or settings Ruff does not implement.
PylintA deeper Python analyzer with inference-based checks and a plugin system.pick this instead when semantic checks, custom checkers, or Pylint-specific rules are more important than execution speed.

What people are saying

  1. [github-trending] astral-sh/ruff

Sources

  1. Ruff README
  2. Ruff FAQ
  3. Known deviations from Black
  4. Ruff versioning policy
  5. Ruff 0.16.2 release
  6. Nix-shell shebang false-positive report