| name | linting |
| description | Python linting with Ruff - an extremely fast linter written in Rust. Use when: (1) Standardizing code quality, (2) Fixing style warnings, (3) Enforcing rules in CI, (4) Replacing flake8/isort/pyupgrade/autoflake, (5) Configuring lint rules and suppressions.
|
Ruff Linting
Ruff is an extremely fast Python linter designed as a drop-in replacement for Flake8 (plus dozens of plugins), isort, pydocstyle, pyupgrade, autoflake, and more. Written in Rust, it offers 10-100x performance improvements over traditional Python linters.
Overview
Ruff provides a single CLI for linting with optional auto-fix. It supports an extensive rule set with 800+ built-in rules and integrates cleanly with pre-commit, CI systems, and modern editors.
Key Features
- Extremely Fast: 10-100x faster than Flake8, Black, isort
- Drop-in Replacement: Compatible with existing Flake8 plugins and configurations
- Auto-fix Support: Automatically fix many common issues
- Comprehensive Rules: 800+ built-in rules from popular linters
- Single Tool: Replaces flake8, isort, pyupgrade, autoflake, pydocstyle, and more
When to Use
- Standardizing code quality across a project or team
- Enforcing consistent coding rules in CI/CD pipelines
- Replacing multiple linting tools with a single fast solution
- Auto-fixing common code style issues
- Migrating from Flake8, isort, or other legacy linters
Quick Start
uv pip install ruff
pip install ruff
ruff check .
ruff check . --fix
ruff check --watch
Core Patterns
- Start minimal: Enable
E and F rules first, then gradually expand
- Auto-fix safely: Use
ruff check --fix for safe fixes only
- Per-file ignores: Use sparingly for generated code or special cases
- CI integration: Use
ruff check --output-format github for GitHub Actions
- Single source of truth: Configure via
pyproject.toml or ruff.toml
Rule Selection
Ruff uses a code system where each rule consists of a 1-3 letter prefix followed by digits (e.g., F401). Rules are controlled via lint.select, lint.extend-select, and lint.ignore.
Recommended Rule Sets
Minimal (Start Here):
[tool.ruff.lint]
select = ["E", "F"]
Balanced (Recommended):
[tool.ruff.lint]
select = [
"E",
"F",
"UP",
"B",
"SIM",
"I",
]
Comprehensive:
[tool.ruff.lint]
select = [
"E",
"W",
"F",
"UP",
"B",
"SIM",
"I",
"N",
"S",
"C4",
"DTZ",
"T20",
"RUF",
]
ignore = ["E501"]
Rule Priority
CLI options override pyproject.toml, which overrides inherited configs:
- CLI (
--select, --ignore) - highest priority
- Current
pyproject.toml
- Inherited
pyproject.toml files
For detailed rule configuration, see references/rule_selection.md.
Configuration
pyproject.toml (Recommended)
[tool.ruff]
line-length = 88
target-version = "py311"
exclude = [".venv", "dist", "build", "*.pyi"]
[tool.ruff.lint]
select = ["E", "F", "UP", "B", "SIM", "I"]
ignore = ["E501"]
fixable = ["ALL"]
unfixable = []
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101"]
"__init__.py" = ["F401"]
"**/{tests,docs,tools}/*" = ["E402"]
[tool.ruff.lint.isort]
known-first-party = ["myproject"]
[tool.ruff.lint.pydocstyle]
convention = "google"
ruff.toml Alternative
line-length = 88
target-version = "py311"
[lint]
select = ["E", "F", "UP", "B", "SIM", "I"]
ignore = ["E501"]
[lint.per-file-ignores]
"tests/**/*.py" = ["S101"]
Fix Safety
Ruff categorizes fixes as safe or unsafe:
| Type | Behavior | Default |
|---|
| Safe | Preserves code semantics | Enabled |
| Unsafe | May change runtime behavior | Disabled |
ruff check --fix
ruff check --fix --unsafe-fixes
ruff check --unsafe-fixes
Adjusting Fix Safety
[tool.ruff.lint]
extend-safe-fixes = ["F601"]
extend-unsafe-fixes = ["UP034"]
fixable = ["ALL"]
unfixable = ["F401"]
For detailed fix safety documentation, see references/fix_safety.md.
Error Suppression
Line-Level (noqa)
x = 1
i = 1
x = 1
File-Level
Block-Level (Preview Mode)
VALUE_1 = "Very long string..."
VALUE_2 = "Another long string..."
For detailed suppression patterns, see references/error_suppression.md.
CLI Commands
ruff check .
ruff check path/to/file.py
ruff check . --fix
ruff check . --fix --unsafe-fixes
ruff check . --output-format text
ruff check . --output-format github
ruff check . --output-format json
ruff check . --output-format sarif
ruff check . --diff
ruff check . --show-fixes
ruff check . --statistics
ruff rule F401
ruff check --watch
ruff check . --add-noqa
ruff check . --extend-select RUF100
Exit Codes
| Code | Meaning |
|---|
| 0 | No violations found, or all fixed |
| 1 | Violations found |
| 2 | Configuration error or internal error |
Modify exit behavior:
ruff check . --exit-zero
ruff check . --exit-non-zero-on-fix
CI Integration
GitHub Actions
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/ruff-action@v3
with:
args: "check --output-format github"
Pre-commit
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Troubleshooting
| Issue | Solution |
|---|
| Rule conflicts with formatter | Ignore formatting rules (E501) when using ruff format |
| Too many violations | Start with minimal rules (E, F), expand gradually |
| Too many per-file ignores | Review rule selection, consider disabling noisy rules |
| Slow on large codebase | Ensure .venv excluded, check for recursive symlinks |
| noqa not working | Check syntax: # noqa: F401 (colon required) |
Common Rule Prefixes
| Prefix | Source | Description |
|---|
| E/W | pycodestyle | Style errors/warnings |
| F | Pyflakes | Logical errors |
| B | flake8-bugbear | Common bugs |
| I | isort | Import sorting |
| UP | pyupgrade | Python version upgrades |
| SIM | flake8-simplify | Code simplification |
| N | pep8-naming | Naming conventions |
| S | flake8-bandit | Security issues |
| C4 | flake8-comprehensions | Comprehension style |
| RUF | Ruff | Ruff-specific rules |
References