Cloud Parts

Ruff

A Python linter and formatter written in Rust that stands in for Flake8 and its plugins, isort, pyupgrade and Black, 10 to 100 times faster.

Type
Open source
Made by
Astral
License
MIT
Facts checked
9 October 2026

What it is

Ruff parses each Python file once and runs its rules over the syntax tree: 968 of them by the count in the 0.16 release notes, re-implementing Pyflakes, pycodestyle, isort, pyupgrade, flake8-bugbear and dozens of other Flake8 plugins natively. Rules are picked by code or prefix (F401, UP, B), and most findings carry a fix that ruff check --fix applies; fixes that could change behaviour are marked unsafe and need an explicit opt-in. Since 0.16 (July 2026) 413 rules are on by default, up from 59, so an unconfigured project already gets import sorting and pyupgrade checks. The same binary also formats: ruff format is designed as a drop-in for Black and formats more than 99.9% of lines identically on Black-formatted projects such as Django, and since 0.16 it also formats Python code blocks inside Markdown files. Configuration lives in pyproject.toml or ruff.toml, with the closest file winning, as in ESLint. ruff server is a language server built into the CLI and powers the VS Code extension.

Ruff is a linter, not a type checker; its own FAQ recommends pairing it with a type checker such as Astral’s ty, mypy, Pyright or Pyre. It is built by Astral, which announced in March 2026 an agreement to join OpenAI’s Codex team and says it will keep developing its tools in the open. Ruff is still 0.x: the minor version marks breaking changes, and 0.17.0 (October 2026) raised the default target to Python 3.11 and trimmed the default rule set again.

Why teams pick it

  • Speed: about 150 times faster than Flake8 at its first release, and its formatter over 30 times faster than Black at launch
  • One tool and one config section replace Flake8 with its plugins, isort, pyupgrade, autoflake and Black
  • Automatic fixes for most findings, with risky ones clearly marked unsafe
  • Useful with zero configuration since 0.16, and new rules wait in preview for at least one minor release before becoming stable

Watch out for

  • No custom or third-party rules: a Flake8 plugin is only available if Ruff’s maintainers re-implement it in Rust
  • No type checking; you still need mypy, Pyright, basedpyright, Pyrefly or ty beside it
  • Pre-1.0 versioning: minor releases change defaults (0.16 grew the default rule set from 59 to 413 rules), so pin the version
  • The formatter differs from Black in a few deliberate ways; Ruff advises against alternating the two on the same code

Alternatives

What all linters have in common →

How it fits with other technologies

Lint and format a file with no configuration (Ruff 0.17.0, default rule set) · bash

uvx ruff check --output-format concise
# orders.py:1:1: I001 [*] Import block is un-sorted or un-formatted
# orders.py:1:8: F401 [*] `os` imported but unused
# orders.py:9:11: UP045 [*] Use `X | None` for type annotations
# Found 3 errors.
# [*] 3 fixable with `--fix`.

uvx ruff rule F401 | head -3     # every rule documents itself
# # unused-import (F401)
# Derived from the **Pyflakes** linter.

uvx ruff format --check          # what CI runs: report, exit 1, change nothing
#   -     orders=[Order(id=1, total_cents=1299), Order(id=2, total_cents=450)]
#   +     orders = [Order(id=1, total_cents=1299), Order(id=2, total_cents=450)]
# 1 file would be reformatted

uvx ruff check --fix && uvx ruff format
# Found 3 errors (3 fixed, 0 remaining).
# 1 file reformatted

See it in a real stack

No architecture uses Ruff yet. Drop it into the playground and wire it up yourself.Open playground →
Where it came from2022–2026

In August 2022 Charlie Marsh pointed at the JavaScript world, where esbuild, swc and Bun had shown that tools rewritten in faster languages could be 10 to 100 times quicker, and argued Python tooling could be “much, much faster”. As a proof of concept Marsh released Ruff, a linter written in Rust on top of RustPython’s parser: about 150 times faster than Flake8 when linting CPython on macOS, with ESLint-style caching and pyproject.toml configuration. Marsh called it “rough” and not a drop-in replacement yet.

Adoption was quick. By April 2023 Ruff had passed a million monthly downloads and was used by Airflow, FastAPI, pandas and SciPy, and Marsh founded Astral with $4 million of seed funding led by Accel to keep building it. The Ruff formatter followed in October 2023, aiming at Black compatibility rather than a new style, and a built-in language server replaced the separate ruff-lsp in 2024.

Astral went on to build uv and ty around the same principles. In March 2026 it agreed to join OpenAI’s Codex team, and Ruff kept shipping: 0.16 in July 2026 expanded the default rule set from 59 to 413 rules.

Why it’s built this way

Rewrite the linter in Rust
Marsh’s hypothesis was that Python tooling could be rewritten in faster languages; the speed-up turned a 12-second lint of CPython into roughly real-time feedback.
Re-implement popular plugins instead of loading them
Keeping every rule native in Rust preserves the speed and one consistent interface, at the cost of user-written rules.
Copy Black’s style rather than invent one
Black was already the de facto style, so near-identical output let projects switch formatters with almost no diff.
Rules start in preview
New rules stay in preview for at least one minor release before they become stable, so upgrades don’t surprise teams with untested checks.

Timeline

  1. 2022

    Ruff released in August as a proof of concept

  2. 2023

    Astral founded in April; the Ruff formatter arrives in October

  3. 2024

    ruff server, a built-in language server, replaces ruff-lsp

  4. 2026

    March: Astral agrees to join OpenAI’s Codex team

  5. 2026

    July: 0.16 enables 413 rules by default and formats Markdown code blocks

  6. 2026

    October: 0.17 targets Python 3.11 by default

Sources14 · facts checked 9 October 2026

Improve this page on GitHub