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 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.
[tool.mypy]python_version = "3.11"strict = truewarn_return_any = truewarn_unused_ignores = truedisallow_untyped_defs = trueWait, that’s mypy config. Here’s Pyright:
{ "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
# Installpip install pyright
# Or use npx (faster, better caching)npx pyright
# Type check your codepyright src/
# Output example:# 0 errors, 0 warnings, 0 informations# Completed in 2.34sAlternative 2: Black for Formatting
For code formatting, Black remains the gold standard. It’s opinionated, consistent, and widely adopted.
[tool.black]line-length = 88target-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
# Installpip install black
# Format all Python filesblack .
# Check without modifyingblack --check .
# Show diffblack --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.
[flake8]max-line-length = 88extend-ignore = E203, W503, E501exclude = .git, __pycache__, build, distmax-complexity = 10
[isort]profile = blackline_length = 88multi_line_output = 3include_trailing_comma = trueforce_grid_wrap = 0use_parentheses = trueensure_newline_before_comments = trueThe 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
# Installpip install flake8 isort
# Check importsisort --check-only --diff .
# Lintflake8 src/
# Auto-fix importsisort .Comparison: What You Give Up
Let me be honest about the trade-offs:
┌──────────────────────────────────────────────────────────┐│ 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:
- Speed: The Rust-based implementation is unmatched
- Integration: One tool vs. coordinating multiple tools
- Auto-fixes: Ruff can fix more issues automatically
- Cache efficiency: Single tool caches better
What you gain:
- Vendor independence: No single corporate owner
- Ecosystem depth: More plugins and extensions
- Maturity: These tools have years of stability
- Transparency: Community-governed development
My Recommended Setup
After testing, here’s what I settled on for my projects:
[tool.black]line-length = 88target-version = ['py310', 'py311', 'py312']
[tool.isort]profile = "black"line_length = 88known_first_party = ["myproject"]
[tool.mypy]python_version = "3.11"strict = truewarn_return_any = truewarn_unused_ignores = trueplugins = ["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:
#!/bin/bashset -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
# ❌ 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!# ✅ RIGHT: Consistent line lengths[tool.black]line-length = 88
[tool.isort]line_length = 88 # Matches Black
[tool.flake8]max-line-length = 88 # All consistentextend-ignore = E203, W503 # Ignore conflicts with BlackMistake 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 Case | Best Alternative | Why |
|---|---|---|
| Type Checking | Pyright | Better inference than ty |
| Formatting | Black | Industry standard |
| Linting | flake8 | Plugin ecosystem |
| Import Sorting | isort | Mature, 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:
- 👨💻 Ruff - An extremely fast Python linter
- 👨💻 Pyright - Static type checker for Python
- 👨💻 Black - The uncompromising code formatter
- 👨💻 OpenAI Acquires Astral
- 👨💻 flake8 - Your Tool For Style Guide Enforcement
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments