Python developers have long relied on a fragmented ecosystem of tools to maintain code quality. Linters like Flake8, formatters like Black, import sorters like isort, and various plugins each served a purpose but collectively created complexity and performance overhead. Ruff, an extremely fast Python linter and code formatter written entirely in Rust, fundamentally changes this landscape by consolidating these tools into one blazingly fast package that executes 10-100x faster than its predecessors.
The story of Ruff begins with a simple observation: Python tooling, while powerful, had become unnecessarily slow. Traditional linting tools written in Python incurred interpreter overhead with each execution, and even optimized tools like Flake8 struggled to keep pace with large codebases. When Charlie Marsh created Ruff, he leveraged Rust's zero-cost abstractions and parallel processing capabilities to reimagine what a Python linter could achieve. The result is a tool that doesn't just match the functionality of existing tools but surpasses them in speed by orders of magnitude.
Ruff's development is backed by Astral, a company dedicated to building high-performance Python tooling. Beyond Ruff, Astral has created uv (a blazingly fast Python package installer) and ty (a modern Python type checker), forming a comprehensive toolkit for Python developers who demand both quality and speed. This ecosystem approach means Ruff isn't a solo project but part of a larger vision for modern Python development.
The impact of Ruff extends beyond individual developer productivity. Teams adopting Ruff report reduced CI/CD pipeline times, fewer code review discussions about style, and more consistent codebase quality. For organizations running Python-based web applications, the speed advantages translate directly to faster development cycles and quicker feedback loops.
Ruff by the Numbers
10-100x
Faster than traditional linters
800+
Built-in rules
1
Tool replaces multiple
0
Configuration files needed
Why Speed Matters in Code Quality Tools
The importance of linting speed extends far beyond mere convenience. When developers run linters manually or as part of their workflow, slow tools create friction that discourages regular use. Developers might skip linting entirely, push code without checking, or face lengthy CI/CD pipelines that delay feedback. Ruff eliminates these pain points by completing linting operations so quickly that they become invisible to the developer's workflow.
Consider the performance metrics that define Ruff's impact. Benchmarking against the CPython codebase--the standard library of Python itself--Ruff completes linting in a fraction of the time required by traditional tools. While Flake8 might take several seconds to scan a large codebase, Ruff completes the same task in milliseconds. This speed advantage compounds over time: a developer who runs linting dozens of times daily saves minutes with each execution, resulting in hours of recovered productivity each week.
The Rust implementation provides more than just raw speed. Rust's memory safety guarantees mean Ruff handles large codebases without memory leaks or unexpected crashes. Its parallel processing capabilities utilize modern multi-core processors effectively, and its compiled nature eliminates the startup overhead associated with Python interpreters. These architectural decisions transform linting from a bottleneck into a seamless background process, enabling teams to focus on building robust web applications rather than waiting for tools to complete.
For development teams practicing continuous integration, Ruff's speed means faster pipeline execution and quicker feedback on pull requests. Rather than waiting minutes for linting results, developers see output in seconds, enabling rapid iteration and reducing the context switching that slows down creative work.
Installing Ruff on Any Platform
Ruff offers installation options for every development environment, from local development machines to Docker containers to CI/CD pipelines. The most straightforward approach uses pip, Python's package manager, which works immediately on any system with Python installed.
System-wide Installation
pip install ruff
This method installs ruff as a command-line tool accessible from any terminal session. Developers working with multiple Python versions can install ruff within specific virtual environments, ensuring version compatibility without affecting system-wide configurations. For projects using pipx--a tool for installing Python applications in isolated environments--ruff installation provides clean separation from other Python packages.
Cargo Installation
For developers already in the Rust ecosystem:
cargo install ruff
This approach compiles ruff from source, allowing customization through compile-time features and ensuring the latest development version. For teams standardized on Homebrew (macOS) or Chocolatey (Windows), community-maintained packages provide familiar installation patterns. Prebuilt binaries distributed through GitHub releases enable automated installation in CI/CD environments without requiring language-specific runtime dependencies.
Docker Integration
FROM python:3.11-slim
RUN pip install ruff
WORKDIR /app
COPY . .
RUN ruff check .
Container-based workflows benefit from ruff's minimal runtime requirements. Adding ruff to a Docker image adds negligible size while providing consistent code quality enforcement across development and production environments. This pattern ensures every container build includes linting validation, catching issues before deployment rather than discovering them in production.
Configuring Ruff for Your Project
Ruff's configuration system prioritizes developer ergonomics while supporting complex project requirements. The tool automatically discovers configuration from standard project files, reducing boilerplate and ensuring consistency across team members' environments.
Basic Configuration
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I"] # Errors, Flake8, isort
ignore = ["E501"] # Line too long (handled by formatter)
The target-version setting ensures rules account for Python version differences, preventing false positives on version-specific syntax. The select directive enables specific rule categories--E (pycodestyle errors), F (pyflakes), and I (isort import sorting)--while the ignore directive excludes individual rules that don't fit the project's standards.
Understanding Rule Categories
| Category | Prefix | Description |
|---|---|---|
| pycodestyle | E, W | PEP 8 style guidelines |
| pyflakes | F | Semantic issues |
| isort | I | Import organization |
| pyupgrade | UP | Modernize for newer Python |
| flake8-bugbear | B | Potential bugs |
| flake8-comprehensions | C4 | Efficient comprehensions |
Ruff implements over 800 rules, spanning code style, bug detection, complexity, security, and import organization. This comprehensive rule set means teams can adopt Ruff without needing additional tools for most common linting scenarios. The plugin rules--originally developed for Flake8--are reimplemented in Rust within Ruff, maintaining compatibility while dramatically improving performance.
Rule Selection
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"UP", # pyupgrade
"B", # flake8-bugbear
"C4", # flake8-comprehensions
]
Individual rule codes override category selections, allowing precise control. This granular control enables teams to adopt Ruff incrementally, ignoring rules that require broader codebase changes while enforcing new rules immediately. For teams working on enterprise Python applications, this flexibility ensures linting can scale with project complexity.
Running Ruff and Using Autofix
Basic Commands
# Check a single file
ruff check mymodule.py
# Check entire project
ruff check src/ tests/
# Format code
ruff format src/
# Autofix issues automatically
ruff check --fix src/
# Show diff without applying
ruff check --diff src/
Example Output
src/auth.py:10:5 F401 `os` imported but unused
src/auth.py:15:1 E501 Line too long (92 > 88 characters)
src/config.py:3:1 UP035 Deprecated import useb in `xml.etree`
Exit codes follow conventional patterns: zero indicates no violations, non-zero codes indicate issues found. This convention enables Ruff integration with shell scripts and CI/CD systems.
Autofix Capabilities
Many Ruff rules support automatic fixing through the --fix flag. This feature transforms Ruff from a detection tool into a correction tool, handling tedious fixes automatically:
ruff check --fix src/
The autofix capability covers rules with clear resolution strategies: removing unused imports, adding missing imports, fixing whitespace issues, and reorganizing import statements. Rules requiring human judgment--architectural decisions, semantic changes--remain unfixed, ensuring automated corrections remain safe.
The --diff option shows what would change without applying fixes, useful for review before committing. Combining --fix with --exit-non-zero-on-fix enables workflows where fixing is expected but violations remaining after fixing trigger failures, ensuring CI pipelines catch both existing violations and new issues introduced during development.
For teams implementing CI/CD pipelines, Ruff's autofix capabilities reduce the manual overhead of maintaining code quality, allowing developers to focus on business logic rather than formatting details.
Everything you need for Python code quality in one tool
Extreme Performance
10-100x faster than existing linters, written in Rust for zero-cost abstractions
All-in-One Tool
Replaces Flake8, Black, isort, pydocstyle, pyupgrade, and autoflake
800+ Rules
Comprehensive rule set covering style, bugs, complexity, and security
Built-in Caching
Automatically skips unchanged files for faster repeated runs
Editor Integration
VS Code extension and LSP support for real-time feedback
Easy Migration
Compatible configuration with existing Python linting tools
Editor Integration for Real-Time Feedback
Editor integration transforms Ruff from a command-line tool into an interactive development companion, providing feedback as code is written rather than after completion. VS Code, the most popular Python editor, supports Ruff through the official extension.
VS Code Configuration
{
"ruff.trace.server": "verbose",
"ruff.check.command": "check",
"editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true
}
}
The Ruff extension for VS Code provides real-time linting feedback, underlining violations as they appear in the editor. Configuration through workspace settings enables customization without modifying project files. The extension requires Ruff to be installed in the project's Python environment or system-wide.
Pre-commit Hook
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Pre-commit hooks provide another integration point, running Ruff before commits are finalized. This pattern catches issues before they enter version control, ensuring committed code meets quality standards regardless of individual developer configurations.
GitHub Actions
name: Lint
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v2
Continuous integration pipelines benefit enormously from Ruff's speed. GitHub Actions, GitLab CI, and other platforms execute Ruff as part of pull request validation, preventing style violations from reaching production code. The official astral-sh/ruff-action handles installation and execution, providing clear failure output when violations occur.
For development teams using modern development workflows, editor integration and CI/CD pipelines work together to ensure code quality at every stage--from local development through production deployment.
Migrating from Existing Tools
Transitioning to Ruff from existing linting tools requires careful planning to maintain code quality while adopting the new tool. The migration strategy depends on current tooling complexity.
From Flake8
# Before (Flake8)
flake8 src/ --select=E,W,F --ignore=E501
# After (Ruff)
ruff check src/
For Flake8 users, Ruff provides a drop-in replacement that maintains compatibility while improving performance. Configuration translation from Flake8's .flake8 or setup.cfg to Ruff's format requires mapping plugin rules to their Ruff equivalents. Flake8-bugbear rules (B prefix) become B in Ruff; flake8-comprehensions (C4) become C4.
From Black
# Replace Black with Ruff formatter
ruff format src/
Black users find Ruff's formatter compatible with Black's output, enabling gradual migration. The --diff flag shows differences between formatters during transition, helping teams verify compatibility before full migration.
Unified Configuration
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = ["E", "W", "F", "I", "UP", "B", "C4"]
ignore = ["E501"]
Unified configuration in pyproject.toml eliminates the need for multiple configuration files. This consolidation reduces configuration management overhead while maintaining equivalent functionality to the original tool suite. Teams can reduce their dependency on multiple tools like Flake8, Black, and isort, replacing them with a single high-performance solution.
For organizations with existing Python codebases, the migration path to Ruff is straightforward. Most projects can replace their current linting stack within a single sprint, gaining immediate performance benefits while maintaining the same level of code quality enforcement.
Advanced Configuration
Per-File Overrides
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"] # Allow unused imports in __init__
"tests/*" = ["S101"] # Allow assert in tests
"legacy/*" = ["UP035"] # Skip upgrade suggestions
Per-file overrides enable exceptions for specific modules. This capability is essential for large codebases where certain files or directories require different linting rules. The extend-safe-fixes and extend-unsafe-fixes categories control which fixes Ruff considers safe to apply automatically versus those requiring review.
Exclusion Patterns
[tool.ruff]
exclude = [
".git",
"venv",
"*/__pycache__",
"*.egg-info",
"dist",
"build",
]
Exclusion patterns prevent Ruff from analyzing generated code, vendored dependencies, or other non-lintable content. Proper exclusion configuration is crucial for monorepos and large projects to avoid false positives from third-party code.
Performance Optimization
Ruff's caching is enabled by default and stores results between runs, skipping unchanged files automatically. This feature is particularly valuable for large monorepos and CI pipelines. The --no-cache flag disables caching when fresh analysis is required, and the --cache-dir option allows custom cache location for projects with specific directory structures.
For teams managing complex Python projects, these advanced configuration options enable fine-tuned control over linting behavior. Whether dealing with legacy code that requires special handling or optimizing for large-scale CI/CD pipelines, Ruff's configuration system adapts to diverse project requirements.
Trusted by Major Open Source Projects
“Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually running and checking the code.”
Sebastián Ramírez Creator, FastAPI
“Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. On our largest module (250k LOC), pylint takes about 2.5 minutes, parallelized across 4 cores. Running ruff against our entire codebase takes .4 seconds.”
Nick Schrock Founder, Elementl
“Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of ~20s. This is an enormous quality of life improvement for local dev.”
Bryan Van de Ven Co-creator, Bokeh
Ruff's adoption by major open-source projects validates its production readiness. Projects including Apache Airflow, FastAPI, Pandas, SciPy, Hugging Face Transformers, Apache Superset, and hundreds of others have integrated Ruff into their development workflows. These adoption patterns demonstrate Ruff's maturity for production use--the tool handles edge cases discovered through real-world usage, maintains backward compatibility, and releases updates regularly.
For organizations evaluating Ruff for their own projects, the ecosystem adoption provides confidence that the tool will continue receiving updates, bug fixes, and new features. The Astral company's backing ensures continued development and support, making Ruff a reliable choice for teams building scalable Python applications.
Getting Started with Ruff Today
Adopting Ruff requires minimal investment while delivering immediate productivity benefits. The recommended approach begins with installation and basic configuration, then expands coverage as the team becomes comfortable.
Quick Start
# 1. Install Ruff
pip install ruff
# 2. Add configuration to pyproject.toml
# (use the basic configuration shown above)
# 3. Run on your codebase
ruff check src/
# 4. Enable autofix
ruff check --fix src/
The investment in Ruff adoption pays dividends through faster development cycles, clearer code standards, and reduced time spent on style discussions. Developers focus on logic and architecture rather than formatting details, while the tool enforces consistency automatically.
Start by installing Ruff using the method appropriate for your environment. Then, create a minimal configuration in your project's root. Run Ruff on your codebase to see current violations, address critical issues first, then expand rule coverage gradually. Enable editor integration for real-time feedback, and add Ruff to pre-commit hooks and CI pipelines for consistent enforcement.
For teams looking to modernize their Python development workflow, Ruff represents an opportunity to consolidate tooling while dramatically improving performance. The transition from multiple tools to a single high-performance linter simplifies maintenance and accelerates development cycles.
Frequently Asked Questions
Does Ruff replace Black for formatting?
Yes, Ruff's formatter (accessed via `ruff format`) is designed to be compatible with Black's output. You can use Ruff as a drop-in replacement for Black in most cases. The formatter follows Black's established conventions, ensuring consistent code style across your codebase.
Is Ruff safe to use for autofix?
Ruff distinguishes between 'safe' fixes (automatically applied) and 'unsafe' fixes (requiring review). Most common fixes like removing unused imports and organizing imports are safe and well-tested. The tool provides clear output about what changes would be made, allowing teams to review before applying.
How do I migrate from multiple Python tools to Ruff?
Start by enabling core rules (E, F, I) that match your current configuration. Gradually add plugin rules as you verify compatibility. The Ruff documentation provides detailed migration guides for each tool, and most teams can complete migration within a single sprint.
Does Ruff support Python 3.14 and newer versions?
Yes, Ruff supports Python 3.14 and maintains compatibility with new Python versions as they are released. Set `target-version` in your configuration to ensure appropriate rule application for your Python version.
Sources
- Astral: Ruff Documentation - Primary source for installation, configuration, features, and command reference
- LogRocket: Linting with Ruff - Practical usage guide with examples and comparisons
- GitHub: astral-sh/ruff - Repository with benchmarks, adoption stats, and community feedback