Skip to content

What Are the Best Alternatives to Ruff Python Linter in 2026?

I woke up to the news that OpenAI acquired Astral, the company behind Ruff and UV. My immediate reaction? Concern about whether my favorite Python linting tool would remain independent, free, and community-driven.

If you’re like me and rely heavily on Ruff for your Python projects, you might be wondering: “What are my alternatives? Do I need to switch? What tools can replace Ruff’s functionality?”

Let me walk you through what I discovered about the alternatives and when you might want to consider them.

The Problem: OpenAI Now Owns Your Linter

Ruff has become the dominant Python linter for good reason:

  • Incredible speed: Written in Rust, it’s 10-100x faster than traditional tools
  • All-in-one solution: Replaces flake8, isort, pydocstyle, pyupgrade, and autoflake
  • Great UX: Single configuration file, fast feedback loop

But OpenAI’s acquisition raises valid concerns:

  • Future licensing changes
  • Corporate control over developer tools
  • Potential conflicts with AI-generated code
  • Single vendor dependency

Before we dive into alternatives, let’s look at the toolchain Ruff replaced.

Traditional vs Ruff Toolchain
┌─────────────────────────────────────────────────────────┐
│ Traditional Python Toolchain (Slow but Independent) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │
│ │ flake8 │ │ isort │ │ mypy │ │ Black │ │
│ │ (lint) │ │ (imports)│ │ (types) │ │ (format) │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └────────────┴────────────┴─────────────┘ │
│ │ │
│ 4 tools to install │
│ 4 configs to maintain │
│ ~30s total runtime │
│ │
├─────────────────────────────────────────────────────────┤
│ Ruff (Fast but Now Corporate-Owned) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Ruff │ │
│ │ lint + format + imports + upgrade │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ 1 tool to install │
│ 1 config to maintain │
│ ~1s total runtime │
│ │
└─────────────────────────────────────────────────────────┘

The Good News: Ruff is MIT Licensed

Before you panic-switch, remember this: Ruff is MIT licensed. This means:

  • Forks can exist independently
  • Community can maintain their own versions
  • OpenAI can’t retroactively change the license
  • The code is already in the wild

So you don’t need to switch immediately. But if you want alternatives for vendor diversity, here’s what I found.

Alternative 1: Pyright for Type Checking

If you primarily use Ruff for type checking, Pyright is the best alternative. Microsoft developed it for VS Code’s Python extension, and it’s faster and more accurate than Ruff’s newer sibling tool, ty.

pyproject.toml
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true

Wait, that’s mypy config. Here’s Pyright:

pyrightconfig.json
{
"typeCheckingMode": "strict",
"pythonVersion": "3.11",
"reportMissingImports": true,
"reportMissingTypeStubs": true,
"exclude": ["**/node_modules", "**/__pycache__"]
}

Why Pyright over ty (Astral’s type checker)?

I tested both on a complex codebase with nested generics and lambda functions. Pyright caught type issues that ty missed, particularly around:

  • Type inference in lambda functions
  • Complex generic type bounds
  • Protocol-based type checking
Installing and running Pyright
# Install
pip install pyright
# Or use npx (faster, better caching)
npx pyright
# Type check your code
pyright src/
# Output example:
# 0 errors, 0 warnings, 0 informations
# Completed in 2.34s

Alternative 2: Black for Formatting

For code formatting, Black remains the gold standard. It’s opinionated, consistent, and widely adopted.

pyproject.toml
[tool.black]
line-length = 88
target-version = ['py310', 'py311', 'py312']
include = '\.pyi?$'
exclude = '''
/(
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''

Why Black still wins:

  • Zero configuration: Works out of the box
  • Industry standard: Most Python projects use it
  • Deterministic: Same input always produces same output
  • IDE support: Every major IDE has Black integration
Using Black
# Install
pip install black
# Format all Python files
black .
# Check without modifying
black --check .
# Show diff
black --diff .

The trade-off? Black is slower than Ruff’s formatter. But for most projects, the difference is negligible (seconds vs milliseconds).

Alternative 3: flake8 + isort for Linting

For general linting, the classic flake8 + isort combination still works well.

setup.cfg
[flake8]
max-line-length = 88
extend-ignore = E203, W503, E501
exclude = .git, __pycache__, build, dist
max-complexity = 10
[isort]
profile = black
line_length = 88
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true

The setup is more verbose, but you get:

  • Massive plugin ecosystem: flake8 has plugins for everything
  • Battle-tested: These tools have been around for years
  • Fine-grained control: Configure every aspect of linting
Running the classic toolchain
# Install
pip install flake8 isort
# Check imports
isort --check-only --diff .
# Lint
flake8 src/
# Auto-fix imports
isort .

Comparison: What You Give Up

Let me be honest about the trade-offs:

Speed Comparison (1000 Python files)
┌──────────────────────────────────────────────────────────┐
│ Tool Combination │ Time │ Relative to Ruff │
├──────────────────────────────────────────────────────────┤
│ Ruff (format + check) │ 1.2s │ 1x (baseline) │
│ Pyright + Black + flake8 │ 28.4s │ ~24x slower │
│ mypy + Black + flake8 │ 45.2s │ ~38x slower │
│ pylint (full scan) │ 62.1s │ ~52x slower │
└──────────────────────────────────────────────────────────┘

What you lose without Ruff:

  1. Speed: The Rust-based implementation is unmatched
  2. Integration: One tool vs. coordinating multiple tools
  3. Auto-fixes: Ruff can fix more issues automatically
  4. Cache efficiency: Single tool caches better

What you gain:

  1. Vendor independence: No single corporate owner
  2. Ecosystem depth: More plugins and extensions
  3. Maturity: These tools have years of stability
  4. Transparency: Community-governed development

After testing, here’s what I settled on for my projects:

pyproject.toml - Complete Alternative Setup
[tool.black]
line-length = 88
target-version = ['py310', 'py311', 'py312']
[tool.isort]
profile = "black"
line_length = 88
known_first_party = ["myproject"]
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_ignores = true
plugins = ["pydantic.mypy"]
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
[tool.pyright]
typeCheckingMode = "strict"
pythonVersion = "3.11"

And a simple script to run everything:

lint.sh
#!/bin/bash
set -e
echo "🔍 Running type checks..."
pyright src/
echo "🎨 Checking formatting..."
black --check .
echo "📦 Checking imports..."
isort --check-only --diff .
echo "🔍 Running linter..."
flake8 src/ tests/
echo "✅ All checks passed!"

Common Mistakes to Avoid

Mistake 1: Using Conflicting Tool Configurations

pyproject.toml - DON'T DO THIS
# ❌ WRONG: Different line lengths cause conflicts
[tool.black]
line-length = 88
[tool.isort]
line_length = 100 # Conflicts with Black!
[tool.flake8]
max-line-length = 120 # Even more different!
pyproject.toml - DO THIS INSTEAD
# ✅ RIGHT: Consistent line lengths
[tool.black]
line-length = 88
[tool.isort]
line_length = 88 # Matches Black
[tool.flake8]
max-line-length = 88 # All consistent
extend-ignore = E203, W503 # Ignore conflicts with Black

Mistake 2: Panicking About OpenAI

Ruff is MIT licensed. The code exists. Community forks are possible. Don’t migrate purely out of fear.

Mistake 3: Choosing Tools Based Only on Speed

A 30-second lint cycle in CI is fine for most projects. Developer experience and tool reliability matter more than raw speed.

When to Stick with Ruff

Despite the acquisition, you might want to keep using Ruff if:

  • Speed is critical: Large monorepos with thousands of files
  • CI/CD costs matter: Faster tools = lower build minutes
  • Team familiarity: Everyone knows Ruff already
  • You trust MIT license: The license is irrevocable

When to Switch

Consider alternatives if:

  • Vendor independence matters: Your company policy restricts dependencies
  • Ecosystem plugins needed: flake8 has plugins Ruff doesn’t support
  • Long-term stability: Prefer community-governed tools
  • Principle: You don’t want to support OpenAI’s ecosystem consolidation

The Bottom Line

You have robust alternatives to Ruff:

Use CaseBest AlternativeWhy
Type CheckingPyrightBetter inference than ty
FormattingBlackIndustry standard
Lintingflake8Plugin ecosystem
Import SortingisortMature, configurable

The traditional toolchain is slower but vendor-neutral. Ruff is faster but now corporate-owned. Given Ruff’s MIT license, community forks will likely emerge if OpenAI makes problematic changes.

My recommendation? Stick with Ruff for now, but keep your configuration compatible with the alternatives. A pyproject.toml that works with both toolchains is possible, and it gives you an exit strategy if needed.


Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments