---
title: "Ruff v0.16.0"
url: https://daily.dev/posts/ruff-v0-16-0-by368rknj
source_url: https://astral.sh/blog/ruff-v0.16.0
type: article
source: "Astral"
published: 2026-07-23T19:20:52.327Z
updated: 2026-07-26T14:31:05.758Z
tags: ["python", "rust"]
reading_time: 7
upvotes: 22
comments: 0
language: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruff v0.16.0

**[Astral](https://daily.dev/sources/astral-sh)** · 7 min read · 22 upvotes · 0 comments

## Summary

Ruff v0.16.0 is released with several notable changes. The default rule set expands from 59 to 413 enabled rules, catching more severe issues like syntax errors and runtime bugs out of the box. New features include formatting Python code blocks embedded in Markdown files, new suppression comment formats (ruff: ignore, ruff: file-ignore) with optional reason strings and rule-name support in preview, and diffs now shown inline in check and format --check output. Twelve rules are stabilized out of preview, and various behavior improvements are included. A small breaking change affects JSON output field nullability.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://astral.sh/blog/ruff-v0.16.0>

## Community take

How the wider developer community reacted, aggregated from 2 discussions and 158 comments across hackernews (as of 2026-07-26).

**TL;DR:** The community is broadly positive about Ruff 0.16's expanded default rules and speed, while a vocal minority debates whether strict automated linting is worth the tradeoffs; most commenters see linters as eliminating wasteful style debates, though some worry about the migration burden and over-enforcement.

**Sentiment:** 55% positive · 30% mixed · 15% skeptical

**The case for**

- Automated linters eliminate endless PR debates about formatting and style, freeing teams to focus on real problems.
- Ruff's speed (sub-second on large codebases) is a genuine differentiator over older multi-linter setups like golangci-lint.
- Enabling 413 rules by default means greenfield projects get useful linting with zero config.
- Strong default linting is especially valuable for agentic/AI coding workflows.
- One commenter shared real upgrade commits showing the new rules caught meaningful issues in a ~3k-line project.

**The pushback**

- Migrating existing codebases to 0.16 can be painful — one commenter reported only ~10% of violations were auto-fixable, leaving 100+ manual fixes on a small codebase.
- Some enforced rules (e.g. flagging `except Exception`, unsorted imports) are seen by critics as cargo-cult enforcement that doesn't prevent real bugs.
- Ruff still hasn't reached v1.0, meaning breaking changes remain possible in minor releases, which frustrates users who run it hundreds of times a day.
- Formatters can collapse intentionally multi-line code (e.g. a dict with an inline comment) into a single line, destroying the author's intent.
- Switching between linting tools (pylint → flake8 → black → ruff) can generate large reformatting commits that pollute git history.

**By community**

- hackernews (mixed): Majority support Ruff's direction and speed, but a heated sub-thread debates whether strict automated linting dehumanizes developers or is simply good team hygiene, and several users flag the painful migration burden from the new default rules.

**Hottest debate:** Whether automated linters improve team code quality or merely enforce arbitrary style preferences at the cost of developer expressiveness and craftsmanship.

**Open questions**

- When will Ruff release v1.0 with a stable API?
- Is there a Go equivalent to Ruff that unifies linting under one fast, opinionated tool?
- How should teams handle the migration burden when Ruff's defaults change significantly between minor versions?
- Can linters ever catch genuinely harmful patterns like overly complex list comprehensions, or only surface-level style issues?

**Highlights**

> Oh, absolutely. I started writing Python professionally in 2010. Whenever a new group of people started working on a Python project, one of the first things they had to decide was tabs versus spaces. Everyone would begin by saying that the question was unimportant and silly, but then immediately add a “but” followed by a detailed justification of their personal preference. That would lead to people spending two full days exchanging arguments and links to blog posts. Worse, sometimes you would start working on a project without having that discussion first, only to discover a few days later that the code was failing because different people had different indentation settings in their IDEs, both regarding tabs versus spaces and the number of spaces. You would then have to pause the work, go back, have the discussion, and decide who was going to fix all the code committed so far. This only stopped when linters became popular. They may be a little like vaccines: when they work, you do not see them working, so it is easy to forget what things were like before. But believe me, when they appeared, they were a breath of fresh air. We could finally focus on discussing the work rather than the conventions. And tabs versus spaces is only one example. There used to be PR discussions about countless style issues throughout the entire lifetime of a project. That was not entirely unreasonable, because a consistent style genuinely makes a project easier to work on. But when every individual convention has to be negotiated by humans, it takes enormous amounts of energy and becomes tedious very quickly.
> — [ludwik on hackernews](https://news.ycombinator.com/item?id=49057762)

> On the 0.16.0 release it was more like 10% autofixable on the codebases I maintain. One of them had 100+ unfixable errors across less than 10k lines of code and tests in total. Previous ruff version labeled it perfectly clean on format and check with default settings. Good thing we have LLM:s that can do the tedious work of checking each case and applying local annotations or updating the config globally! If I was stuck doing this manually, I would have just gotten rid of ruff and went back to black+pylint.
> — [apelapan on hackernews](https://news.ycombinator.com/item?id=49057504)

> You know how many bugs I've met working on large Python codebases over 20 years, caused by unsorted imports or `except Exception`? Yeah, you've guessed it: exactly 0 bugs. It's really annoying how many people think that if you enforce stupidly strict rules about formatting, more strict that those of Fortran in 70s, you'll automatically get good code. I've seen companies that enable 100% of ruff rules, use several other linters, and enforce other rules (like every variable name should be at least 20 characters long to fully describe its purpose). And they have awful buggy unmaintainable code. But it is nicely formatted (although reading code where half of the screen estate is consumed by the variable name is a bit difficult) and has no "dreadful" `except Exception`. Or every mutable class attribute variable is annotated with `typing.ClassVar` (RUF012 - the most idiotic rule I've ever seen). Nevermind that it doesn't really stop anyone from changing value of that attribute. You must annotate it with `ClassVar`! It's an idiotic cargo-cult.
> — [anticodon on hackernews](https://news.ycombinator.com/item?id=49058556)

> It does and it is even better. It is called the Go Analysis Framework (https://pkg.go.dev/golang.org/x/tools/go/analysis). It is fairly new so not well known but it is what powers go fix and go vet under the hood. And I believe the Go team is currently working on making it possible for module authors to easily describe their own custom analysis passes that would run automatically when running go fix. It is extremely easy to define your own analysis.Analyzer struct that describes your own static analysis pass. You get access to all sorts of useful information such as the AST, types, even SSA info and you can even compose the information between analyzers. Then you can easily compile it into a binary and run it by passing that binary to go fix with a command line flag. The go toolchain itself handles all the complex caching logic so that your analyzers run fast. Since it is made by the go team itself and part of the toolchain it should slowly become the unified standard you are looking for. So hopefully golangci-lint and others should eventually all unify under this framework. You can easily give it a go by telling some AI agent to write some Go Analysis analyzers and telling them to drive them with go fix. My Go projects tend to accumulate a bunch of these to enforce all sorts of rules deterministically and automatically instead of some imprecise markdown file.
> — [gopherino on hackernews · 3 comments](https://news.ycombinator.com/item?id=49056895)

> I've read through all the sub-comments you've left here. In short, you seem to have a grievance against linters that goes way past reasonable.  You assert this example you give is "perfect" below.  You also complain linters waste time and commits despite able evidence in the field they do the opposite. You seem willing to add drama, grievance, and personal bias to what could have been a rather straightforward technical discussion.  The sum of which is: linters sometimes make changes to code that I don't like. I'd encourage you to reconsider what's really important when it comes to team development and try listening more to those around you.  You seem overly focused on asserting your opinion instead of having a discussion. These types of exchanges are usually very unproductive and stressful in a team environment.  They are evidence, IMO, of a dev having the wrong priorities.  I'd encourage you to step back and really consider how you view craftsmanship in a team dynamic and whether or not you are fighting the right battles.
> — [rsyring on hackernews](https://news.ycombinator.com/item?id=49058507)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=49056112) · 81 points · 158 comments
- [hackernews](https://news.ycombinator.com/item?id=49034448) · 3 points · 0 comments

---

Tags: [#python](https://daily.dev/tags/python), [#rust](https://daily.dev/tags/rust)

[View this post on daily.dev](https://daily.dev/posts/ruff-v0-16-0-by368rknj)
