On July 23, Astral released Ruff v0.16.0, and for most projects the headline change fits in one sentence: after upgrading, ruff check runs 413 rules out of the box with zero configuration — seven times the 59 rules the previous version enabled by default. The official blog post puts it right in the title: “Ruff now enables 413 rules by default, up from 59.”
Defaults are a tool’s philosophy statement. Raising the default rule count sevenfold means Astral now considers strict-out-of-the-box the baseline expectation for Python projects. Before you upgrade, it is worth understanding what changed and why.
What Changed: Default Rules Go From 59 to 413
This is not a spur-of-the-moment rule dump. It is the closing move of Ruff’s long-running rule recategorization project (issue #1774), in which the team re-evaluated opt-in rules one by one and promoted the ones that proved stable and high-signal into the default set. The total rule count has also grown from 708 at v0.1.0 to 968 now.
The confidence to enable so much by default comes from performance: Ruff is written in Rust, and a full-rules scan is still faster than older tools running a handful of checks. When the cost of checking approaches zero, “enable everything, disable per case” becomes the rational strategy. For a sense of scale, a default-on Ruff now covers categories many projects used to enable selectively — correctness checks, likely bugs, suspicious patterns — with no configuration at all. Projects that maintain a hand-curated enable-list may find most of it redundant, and brand-new projects get a sensible baseline from ruff check alone.
Eighteen Rules Left the Default Set
Rules were also subtracted. Eighteen opinionated pycodestyle and pyflakes rules were dropped from the defaults, including E401 (multiple imports on one line), E711/E712 (comparisons to None and True), E731 (assignment of lambda), E741 (ambiguous variable names), and F403 (star imports). These have long been sources of style arguments; the release provides a config snippet so projects that want the old behavior can restore it.
The direction is clear: defaults should be high-signal and low-controversy, while style preferences belong to the user. That is the opposite of the “defaults keep getting looser” path many linters have taken — Ruff enables the error-like rules everywhere and lets the style rules yield. E711 and E712 are a useful example: comparing with is None is safer, but forcing that rewrite across a legacy codebase at once is exactly the kind of change that belongs behind an explicit decision, not a silent default.
Markdown Formatting and New Suppression Comments
v0.16 also ships two practical feature groups. First, Ruff can now format Python code blocks embedded in Markdown files, covering python, pyi, and pycon fenced blocks plus Quarto {python} blocks — example code in documentation finally gets the same formatting pass as the codebase itself.
Second, suppression syntax is now complete: new ruff: ignore comments (inline or on the preceding line) and ruff: file-ignore for whole files, joining the ruff: disable/ruff: enable pairs introduced in v0.15. All of them accept an optional reason, and a new --add-ignore flag generates them for you. Also worth noting: check and format --check output now shows fix diffs inline, format --check supports JSON and GitHub/GitLab annotation formats, and 12 rules graduated from preview to stable. For teams that keep runbooks, tutorials, or data docs in Markdown, the formatting change closes a real gap: examples in documentation used to sit outside the formatter’s reach and quietly drifted from house style.
One small breaking change: some JSON output fields (such as filename and location) can now be null, so anything parsing that output should be checked.
Upgrade Notes
Three practical steps. First, run ruff check locally after upgrading and look at the volume of new diagnostics before touching CI — a direct upgrade will likely surface a batch of new failures. Then decide rule by rule whether to adopt and fix, or restore the old defaults with the official config snippet. Second, pin the version, so a change in defaults becomes one reviewable, revertible commit instead of something that drifts in through a dependency. Third, if your project has many Python examples in documentation, the formatting scope just grew; it is a good moment to fold Markdown into the checked set. None of this changes what Ruff is for — it changes how much of it you get before writing any configuration, and the release notes mark every behavior change, which makes the upgrade path unusually legible.
Sources
AI-assisted summary compiled from the sources above, reviewed by a human before publishing.
