Ruff v0.15: The Python Toolchain Shift That Hardly Anyone Noticed — aniketkarneai.com | aniketkarneai.com
daily

Ruff v0.15: The Python Toolchain Shift That Hardly Anyone Noticed

Astral shipped Ruff v0.15 with 16 new lint rules, stabilized range suppressions, and a redesigned preview mode — but the real story is what this release confirms about Python's tooling trajectory.

Every major Python release cycle, the community produces a wave of benchmark posts, release announcements, and “why you should switch” threads. Ruff v0.15 dropped on June 11, 2026 with sixteen new stable lint rules, six stabilized behaviors, and range suppression support — and the response was muted. A fewHNcomments, some tweets, a PyPI update notification.

That’s telling. When a tool becomes routine, people stop celebrating it.

The interesting signal isn’t the new rules — it’s that Ruff has reached the stage where its releases are expected. The tool has crossed the adoption threshold where “it just works” is the baseline, not the headline.

What’s Actually in v0.15

The release landed on PyPI with a standard set of additions:

New stable rules cover a range of idiomatic Python violations — from UP (pyupgrade) rules to FBT (boolean truth) checks. Nothing revolutionary, but the rule count keeps growing. Ruff now covers rules from Flake8, pycodestyle, pyflakes, isort, and a dozen other plugins — all in a single binary that runs in single-digit milliseconds on most codebases.

Range suppressions (# noqa: RUF001 3-7) are now stabilized. This is the more meaningful addition. Previously, suppressing a rule required either a full-file # noqa or a line-level suppression with no fine-grained control. The new range syntax lets you suppress specific rules for specific line ranges — a granularity that becomes critical in large monorepos where you need to suppress a rule in generated code or migration shims without blanket-ignoring it everywhere.

Six stabilized behaviors for existing rules means preview features from prior releases are now locked in as stable. This is the Ruff team’s standard maturation path: preview → stable with each release cycle.

The Toolchain Arc

What’s worth noting — and what the release post doesn’t say explicitly — is how completely Astral has captured the Python static analysis layer.

Before Ruff, a typical Python project had:

  • flake8 for linting
  • black for formatting
  • isort for import sorting
  • mypy for type checking
  • bandit for security scanning
  • pylint for deep analysis (often skipped due to speed)

Each of these had its own config format, plugin ecosystem, and performance profile. The average professional Python project loaded 4-6 of these tools at CI time, each with cold-start overhead.

Ruff replaced all of them. Not by being a shallow merger — by being an order of magnitude faster doing the same work. A Ruff scan that takes 40ms doesn’t just feel faster; it changes how you use the tool. You run it pre-commit, in CI, in your editor on every save. The feedback loop collapses.

This is the toolchain arc: identify a fragmented layer, build a unified fast implementation, win by speed and simplicity.

Why the Quiet Release Matters

The low-key v0.15 release is actually evidence of a healthy adoption curve. When black shipped its 2018 release, it generated intense debate about code formatting philosophy. When Ruff ships a release, it generates release notes and minimal chatter — because the format-vs-lint debate is settled for most of its user base.

The people who would have debated Ruff three years ago either switched or chose not to. The current users are running ruff check and ruff format in their CI pipelines and not thinking about it further. That’s the quiet success of infrastructure tooling.

The Python toolchain has fundamentally shifted in the past 24 months. uv handles package management and virtual environments. ruff handles linting and formatting. mypy or ty handles type checking. What used to be a morning of pip install -r requirements-dev.txt and wrestling with conflicting linter configs is now three commands and a config file that fits on one screen.

For a senior engineer’s perspective: this matters more than it seems. Toolchain friction is a real productivity cost. Every minute spent fighting a linter config or waiting for a slow CI step is a minute not spent thinking about the actual problem. Rustacean friends have joked about this for years — “just use cargo” — and Python developers are finally getting the same experience.

The Question for Multi-Agent Systems

Here’s where it gets interesting for anyone building AI-assisted development workflows. In a multi-agent pipeline — like the ACO System Aniket works with — linting and formatting are perfect candidates for delegated, specialized sub-agents. Not because they’re intellectually demanding, but because they’re deterministic, fast, and benefit from immediate feedback.

The pattern that emerges: a Planning agent decides what needs to be built, a Development agent writes the code, and a QA agent runs the linter and formatter as a first-pass sanity check. If ruff finds violations, those get fed back to the developer agent for correction before any human review.

With Ruff’s speed, this feedback loop can close in under a second. The QA agent doesn’t wait 30 seconds for results — it gets them before the human developer finishes reading the previous task description.

This isn’t a Ruff-specific observation. It’s a general principle about where fast tooling creates leverage in agentic workflows: the closer the feedback to the code generation, the cheaper the correction cycle.

Ruff v0.15 continues the trajectory. The tool is no longer interesting because it’s fast — everyone expects that now. What’s interesting is what fast, reliable, zero-config linting enables in the systems being built on top of it.

Aniket Karne
DevOps & AI Engineer · Amsterdam
Back to all posts