ruff Linting
Expert knowledge for using ruff check as an extremely fast Python linter with comprehensive rule support and automatic fixing.
Core Expertise
ruff Advantages
-
Extremely fast (10-100x faster than Flake8)
-
Written in Rust for performance
-
Replaces multiple tools (Flake8, pylint, isort, pyupgrade, etc.)
-
Auto-fix capabilities for many rules
-
Compatible with existing configurations
-
Over 800 built-in rules
Basic Usage
Simple Linting
Lint current directory
ruff check
Lint specific files or directories
ruff check path/to/file.py ruff check src/ tests/
IMPORTANT: Pass directory as parameter to stay in repo root
✅ Good
ruff check services/orchestrator
❌ Bad
cd services/orchestrator && ruff check
Auto-Fixing
Show what would be fixed (diff preview)
ruff check --diff
Apply safe automatic fixes
ruff check --fix
Fix specific files
ruff check --fix src/main.py
Fix with preview (see changes before applying)
ruff check --diff services/orchestrator ruff check --fix services/orchestrator
Output Formats
Default output
ruff check
Show statistics
ruff check --statistics
JSON output for tooling
ruff check --output-format json
GitHub Actions annotations
ruff check --output-format github
GitLab Code Quality report
ruff check --output-format gitlab
Concise output
ruff check --output-format concise
Rule Selection
Common Rule Codes
Code Description Example Rules
E
pycodestyle errors E501 (line too long)
F
Pyflakes F401 (unused import)
W
pycodestyle warnings W605 (invalid escape)
B
flake8-bugbear B006 (mutable default)
I
isort I001 (unsorted imports)
UP
pyupgrade UP006 (deprecated types)
SIM
flake8-simplify SIM102 (nested if)
D
pydocstyle D100 (missing docstring)
N
pep8-naming N806 (variable naming)
S
flake8-bandit (security) S101 (assert usage)
C4
flake8-comprehensions C400 (unnecessary generator)
Selecting Rules
Select specific rules at runtime
ruff check --select E,F,B,I
Extend default selection
ruff check --extend-select UP,SIM
Ignore specific rules
ruff check --ignore E501,E402
Show which rules would apply
ruff rule --all
Explain a specific rule
ruff rule F401
Rule Queries
List all available rules
ruff rule --all
Search for rules by pattern
ruff rule --all | grep "import"
Get detailed rule explanation
ruff rule F401
Output: unused-import (F401)
Derived from the Pyflakes linter.
Checks for unused imports.
List all linters
ruff linter
JSON output for automation
ruff rule F401 --output-format json
Configuration
pyproject.toml
[tool.ruff]
Line length limit (same as Black)
line-length = 88
Target Python version
target-version = "py311"
Exclude directories
exclude = [ ".git", ".venv", "pycache", "build", "dist", ]
[tool.ruff.lint]
Enable specific rule sets
select = [ "E", # pycodestyle errors "F", # Pyflakes "B", # flake8-bugbear "I", # isort "UP", # pyupgrade "SIM", # flake8-simplify ]
Disable specific rules
ignore = [ "E501", # Line too long (handled by formatter) "B008", # Function calls in argument defaults ]
Allow automatic fixes
fixable = ["ALL"] unfixable = ["B"] # Don't auto-fix bugbear rules
Per-file ignores
[tool.ruff.lint.per-file-ignores] "init.py" = ["F401", "E402"] "tests/**/*.py" = ["S101"] # Allow assert in tests
ruff.toml (standalone)
Same options as pyproject.toml but without [tool.ruff] prefix
line-length = 100 target-version = "py39"
[lint] select = ["E", "F", "B"] ignore = ["E501"]
[lint.isort] known-first-party = ["myapp"] force-single-line = true
Advanced Usage
Per-File Configuration
Override settings for specific paths
ruff check --config path/to/ruff.toml
Use inline configuration
ruff check --select E,F,B --ignore E501
Targeting Specific Issues
Check only specific rule codes
ruff check --select F401,F841 # Only unused imports/variables
Security-focused check
ruff check --select S # All bandit rules
Import organization only
ruff check --select I --fix
Docstring checks
ruff check --select D
Integration Patterns
Check only changed files (git)
git diff --name-only --diff-filter=d | grep '.py$' | xargs ruff check
Check files modified in branch
git diff --name-only main...HEAD | grep '.py$' | xargs ruff check
Parallel checking of multiple directories
ruff check src/ & ruff check tests/ & wait
Combine with other tools
ruff check && pytest && ty check
CI/CD Integration
Pre-commit Hook
.pre-commit-config.yaml
repos:
-
repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.14.0 hooks:
Linter with auto-fix
- id: ruff-check args: [--fix]
Advanced configuration
- id: ruff-check
name: Ruff linter
args:
- --fix
- --config=pyproject.toml
- --select=E,F,B,I types_or: [python, pyi, jupyter]
GitHub Actions
.github/workflows/lint.yml
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'
changed-files: 'true'
# Or using pip
- name: Install ruff
run: pip install ruff
- name: Run linter
run: ruff check --output-format github
GitLab CI
.gitlab-ci.yml
Ruff Check: stage: build image: ghcr.io/astral-sh/ruff:0.14.0-alpine script: - ruff check --output-format=gitlab > code-quality-report.json artifacts: reports: codequality: code-quality-report.json
Common Patterns
Finding Specific Issues
Find unused imports
ruff check --select F401
Find mutable default arguments
ruff check --select B006
Find deprecated type usage
ruff check --select UP006
Security issues
ruff check --select S
Code complexity
ruff check --select C901
Find all TODOs
ruff check --select FIX # flake8-fixme
Gradual Adoption
Start with minimal rules
ruff check --select E,F
Add bugbear
ruff check --select E,F,B
Add import sorting
ruff check --select E,F,B,I --fix
Add pyupgrade
ruff check --select E,F,B,I,UP --fix
Generate baseline configuration
ruff check --select ALL --ignore <violations> > ruff-baseline.toml
Refactoring Support
Auto-fix all safe violations
ruff check --fix
Preview changes before fixing
ruff check --diff | less
Fix only imports
ruff check --select I --fix
Modernize code
ruff check --select UP --fix
Simplify comprehensions
ruff check --select C4,SIM --fix
Plugin Configuration
isort (Import Sorting)
[tool.ruff.lint.isort] combine-as-imports = true known-first-party = ["myapp"] section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
flake8-quotes
[tool.ruff.lint.flake8-quotes] docstring-quotes = "double" inline-quotes = "single" multiline-quotes = "double"
pydocstyle
[tool.ruff.lint.pydocstyle] convention = "google" # or "numpy", "pep257"
pylint
[tool.ruff.lint.pylint] max-args = 10 max-branches = 15 max-returns = 8 max-statements = 60
Best Practices
When to Use ruff check
-
Code quality enforcement
-
Pre-commit validation
-
CI/CD pipelines
-
Refactoring assistance
-
Security scanning
-
Import organization
Critical: Directory Parameters
-
✅ Always pass directory as parameter: ruff check services/orchestrator
-
❌ Never use cd: cd services/orchestrator && ruff check
-
Reason: Parallel execution, clearer output, tool compatibility
Rule Selection Strategy
-
Start minimal: select = ["E", "F"] (errors + pyflakes)
-
Add bugbear: select = ["E", "F", "B"]
-
Add imports: select = ["E", "F", "B", "I"]
-
Add pyupgrade: select = ["E", "F", "B", "I", "UP"]
-
Consider security: select = ["E", "F", "B", "I", "UP", "S"]
Fixable vs Unfixable
-
Mark uncertain rules as unfixable to review manually
-
Common unfixables: B (bugbear), F (pyflakes F401)
-
Let ruff fix safe rules: I (isort), UP (pyupgrade)
Common Mistakes to Avoid
-
Using cd instead of passing directory parameter
-
Enabling ALL rules immediately (use gradual adoption)
-
Not using --diff before --fix
-
Ignoring rule explanations (ruff rule <code> )
-
Not configuring per-file ignores for special cases
Quick Reference
Essential Commands
Basic operations
ruff check # Lint current directory ruff check path/to/dir # Lint specific directory ruff check --diff # Show fix preview ruff check --fix # Apply fixes
Rule management
ruff rule --all # List all rules ruff rule F401 # Explain rule F401 ruff linter # List all linters
Output formats
ruff check --statistics # Show violation counts ruff check --output-format json # JSON output ruff check --output-format github # GitHub Actions format
Selection
ruff check --select E,F,B # Select rules ruff check --ignore E501 # Ignore rules ruff check --extend-select UP # Extend selection
Configuration Hierarchy
-
Command-line arguments (highest priority)
-
ruff.toml in current directory
-
pyproject.toml in current directory
-
Parent directory configs (recursive)
-
User config: ~/.config/ruff/ruff.toml
Common Rule Combinations
Minimal safety
ruff check --select E,F
Good default
ruff check --select E,F,B,I
Comprehensive
ruff check --select E,F,B,I,UP,SIM
Security-focused
ruff check --select E,F,B,S
Docstring enforcement
ruff check --select D --config '[lint.pydocstyle]\nconvention = "google"'
This makes ruff check the preferred tool for fast, comprehensive Python code linting.