← All posts

Testing

Ruff: The Python Linter Fast Enough to Run on Every Keystroke

Ruff is a Rust-built Python linter and formatter that replaces Flake8, isort, and Black with one very fast binary.

R Testing

Python's linting and formatting story used to mean a pile of separate tools - Flake8 for lint, isort for imports, Black for formatting, pyupgrade for modernizing, plus a dozen plugins - each slow enough that you ran them in CI and hoped. Ruff collapses all of that into one Rust-built binary that runs 10 to 100 times faster than the tools it replaces, fast enough to lint on save without noticing the delay.

One Tool for What Took Five

Ruff reimplements hundreds of lint rules from Flake8 and its plugin ecosystem, plus import sorting and code upgrades, under a single command and a single config block in pyproject.toml. Most projects can retire several dependencies the day they adopt it.

Fast Enough to Feel Instant

The speed isn't a vanity metric - it changes behavior. When linting a whole project takes milliseconds, you run it constantly instead of dreading it, and your editor can show issues as you type:

# Lint and auto-fix in place ruff check --fix . # Format like Black ruff format . # CI-friendly output for GitHub annotations ruff check --output-format=github .

Lint and Format Together

Ruff ships both a linter and a Black-compatible formatter, so one tool handles both jobs with consistent behavior. Autofix resolves a large share of findings automatically, and rules are opt-in by category, so you can adopt gradually rather than drowning in warnings on day one.

Rough Edges and Limitations

  • Python-only. It's superb at its job and only its job; a polyglot repo still needs other linters.
  • Not every plugin rule exists yet. Coverage is broad and growing, but a niche Flake8 plugin may not be reimplemented.
  • Opinionated formatting. The formatter is Black-style; if you have strong custom formatting preferences, expect to accept its choices.
  • Fast iteration. Rules and defaults evolve quickly; pin the version in CI for reproducible runs.

If you write any Python at all, Ruff is close to a free upgrade: fewer dependencies, one config, and linting so fast you'll actually leave it on.

Internal link suggestion: link "lint on save" to the ESLint post, its JavaScript-world counterpart for auditing AI-written code.