Python linting and formatting with ruff. Extremely fast linter and formatter replacing Flake8, Black, isort, and pyupgrade. Use when linting, formatting, or checking Python code quality. Triggers: "ruff", "lint python", "format python", "[tool.ruff]".
Install
npx skillscat add ven0m0/claude-config/ruff Install via the SkillsCat registry.
SKILL.md
ruff
Ruff is an extremely fast Python linter and code formatter written in Rust. It replaces
Flake8, isort, Black, pyupgrade, autoflake, and dozens of other tools.
When to Use ruff
Always use ruff for Python linting and formatting, especially if you see:
[tool.ruff]section inpyproject.toml- A
ruff.tomlor.ruff.tomlconfiguration file
Avoid unnecessary changes:
- Don't format unformatted code - If
ruff format --diffshows changes throughout
an entire file, the project likely isn't using ruff for formatting. Skip to avoid
obscuring actual changes. - Scope fixes to code being edited - Use
ruff check --diffto see fixes relevant
to the code you're changing.
How to Invoke ruff
uv run ruff ... # When ruff is in project dependencies (use pinned version)
uvx ruff ... # When ruff is not a project dependency
ruff ... # When ruff is installed globallyLinting
Basic Commands
ruff check # Check current directory
ruff check path/to/file.py # Check specific file
ruff check src/ tests/ # Check multiple directories
ruff check --fix # Auto-fix fixable violations
ruff check --fix --unsafe-fixes # Include unsafe fixes (review first!)
ruff check --watch # Watch for changesImportant: Always pass directory as parameter, don't use cd:
# ✅ Good
ruff check services/orchestrator
# ❌ Bad
cd services/orchestrator && ruff checkRule Selection
ruff check --select E,F,B,I # Select specific rules
ruff check --extend-select UP,SIM # Extend default selection
ruff check --ignore E501,E402 # Ignore specific rules
ruff rule F401 # Explain a specific rule
ruff linter # List available lintersCommon Rule Codes
| Code | Description | Example |
|---|---|---|
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) |
S |
flake8-bandit | S101 (assert usage) |
C4 |
flake8-comprehensions | C400 (unnecessary generator) |
Output Formats
ruff check --statistics # Show violation counts
ruff check --output-format json # JSON output
ruff check --output-format github # GitHub Actions annotations
ruff check --output-format gitlab # GitLab Code Quality reportFormatting
Basic Commands
ruff format # Format current directory
ruff format path/to/file.py # Format specific file
ruff format --check # Check if formatted (exit 1 if not)
ruff format --diff # Show diff without modifyingFormat Workflow
- Preview:
ruff format --diff(see changes) - Check:
ruff format --check(CI validation) - Apply:
ruff format(modify files) - Verify:
ruff format --check(confirm)
Combined Workflow
Run linting fixes before formatting:
ruff check --fix && ruff formatConfiguration
pyproject.toml
[tool.ruff]
line-length = 88
target-version = "py311"
exclude = [".git", ".venv", "__pycache__", "build", "dist"]
[tool.ruff.lint]
select = ["E", "F", "B", "I", "UP", "SIM"]
ignore = ["E501"]
fixable = ["ALL"]
unfixable = ["B"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401", "E402"]
"tests/**/*.py" = ["S101"]
[tool.ruff.lint.isort]
known-first-party = ["myapp"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
docstring-code-format = true
line-ending = "auto"ruff.toml (standalone)
line-length = 88
target-version = "py311"
[lint]
select = ["E", "F", "B", "I"]
ignore = ["E501"]
[lint.isort]
known-first-party = ["myapp"]
[format]
quote-style = "double"
indent-style = "space"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:
- id: ruff-check
args: [--fix]
- id: ruff-formatGitHub 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'Migration from Other Tools
Black → ruff format
black . → ruff format .
black --check . → ruff format --check .
black --diff . → ruff format --diff .Flake8 → ruff check
flake8 . → ruff check .
flake8 --select E,F → ruff check --select E,Fisort → ruff check
isort . → ruff check --select I --fix
isort --check . → ruff check --select ICommon Patterns
Find Specific Issues
ruff check --select F401 # Unused imports
ruff check --select B006 # Mutable default arguments
ruff check --select S # Security issues
ruff check --select C901 # Code complexityGradual Adoption
# Start minimal
ruff check --select E,F
# Add bugbear
ruff check --select E,F,B
# Add imports
ruff check --select E,F,B,I
# Add pyupgrade
ruff check --select E,F,B,I,UPCheck Changed Files
git diff --name-only --diff-filter=d | grep '\.py$' | xargs ruff check
git diff --name-only main...HEAD | grep '\.py$' | xargs ruff formatBest Practices
Rule Selection Strategy:
- Start minimal:
select = ["E", "F"] - Add bugbear:
select = ["E", "F", "B"] - Add imports:
select = ["E", "F", "B", "I"] - Add pyupgrade:
select = ["E", "F", "B", "I", "UP"]
Fixable vs Unfixable:
- Mark uncertain rules as
unfixablefor manual review - Common unfixables:
B(bugbear), someFrules - Safe to auto-fix:
I(isort),UP(pyupgrade)
Critical: Directory Parameters
- ✅ Always pass directory:
ruff check services/orchestrator - ❌ Never use cd:
cd services/orchestrator && ruff check