Ruff Linter & Formatter Basics
The Too-Many-Tools Problem
Before Ruff, Python developers needed three separate tools to write clean code:
| Tool | Job | Problem |
|---|---|---|
| Black | Format code style | Opinionated; no configuration |
| isort | Sort imports alphabetically | Does only one thing |
| Flake8 | Find code errors and style violations | Slow |
A beginner would ask: "Which tool do I use?" Answer: "All three, in that order."
Ruff solves this: One tool does the job of all three—and runs 10–100x faster.
Source: Verified in intelligence/001-verified-tool-documentation.md
What Ruff Does: Format + Lint (Tier 1: Understand)
Ruff has two jobs:
1. Formatting — Make code look consistent
- Fix spacing:
x=1becomesx = 1 - Fix quotes:
'hello'becomes"hello"(configurable) - Add blank lines between functions
- Proper indentation
Result: Your code looks professional, follows Python conventions (PEP 8)
2. Linting — Find likely bugs and style problems
- Unused imports:
import os(never used) - Unused variables:
x = 5(assigned but never read) - Potential bugs:
if x = 5:(assignment instead of comparison) - Line too long: 120+ characters on one line
Result: You catch problems before they cause issues
Installing Ruff (Tier 1: Direct Command)
You already have uv. Installing Ruff is one command:
uv add ruff --dev
The --dev flag means Ruff is a development dependency—you need it while coding, but not when your program runs in production.
Verify installation:
uv run ruff --version
Expected output: ruff 0.14.5 (or similar version number)
Formatting Your Code (Tier 1: Direct Command)
Let's create a messy Python file and watch Ruff fix it.
Create a file messy.py:
Loading Python environment...
Observe the mess:
- Extra spaces around
defand function parameters - Inconsistent quotes (
'hello'is single-quoted) - No spaces around operators (
x+y+z)
Run Ruff formatter:
uv run ruff format messy.py
Expected output:
1 file reformatted
Look at your file now:
Loading Python environment...
What changed:
- Single quotes → double quotes
- Extra spaces removed
- Operators have spaces:
x + y + z - Two blank lines before function definition (PEP 8 standard)
Note: This code demonstrates Ruff's formatting, not Python programming. You'll learn Python functions in Chapter 18.
Checking for Errors (Linting) (Tier 1: Direct Command)
Formatting makes code look good. Linting finds actual bugs.
Create a file buggy.py:
Loading Python environment...
The problems:
- You imported
osbut never used it - You imported
sysbut never used it
Run Ruff linter:
uv run ruff check buggy.py
Expected output:
F401 [*] `os` imported but unused
F401 [*] `sys` imported but unused
Found 2 errors.
[*] 2 fixable with the `--fix` option.
Read the output:
F401: Ruff code for "unused import"[*]: Means Ruff can auto-fix this error- "2 fixable": Both errors can be automatically removed
Auto-Fixing Errors (Tier 1: Direct Command)
You don't have to manually fix linting errors—Ruff can do it:
uv run ruff check buggy.py --fix
Expected output:
Fixed 2 errors.
Check your file:
Loading Python environment...
The unused imports are gone! Ruff removed them automatically.
Ruff Error Codes (Tier 1: Know What They Mean)
Ruff uses short codes to identify problem types:
| Code | Meaning | Fixable? |
|---|---|---|
| F401 | Import not used | Yes |
| E501 | Line too long | No (just warns) |
| E225 | Missing whitespace around operator | Yes |
| F841 | Variable assigned but not used | Yes |
| E203 | Whitespace before colon | Yes |
Key insight: You don't memorize these codes. If you see an error, ask AI: "What does F401 mean and how do I fix it?"
Source: Verified in intelligence/001-verified-tool-documentation.md
When to Format, When to Lint (Tier 1: Decision-Making)
Format when:
- You're done writing a section of code
- Before committing to git
- Every time you save (Zed can do this automatically, Chapter 11)
Lint when:
- You finish a function or module
- Before running tests
- As part of your review process
Best practice: Run both:
uv run ruff format . # Fix all style issues
uv run ruff check . # Find remaining problems
Configuration: Where Rules Live (Tier 2: Preview)
Ruff reads configuration from pyproject.toml in your project root.
You haven't configured anything yet (Ruff works with defaults). But in Lesson 9, you'll customize which rules to enable/disable.
For now, just know:
- Default Ruff rules are sensible (follow PEP 8, catch common bugs)
- You'll configure specific rules when you need non-defaults
Try With AI
What's the difference between linting and formatting, and when should you ignore Ruff warnings?
🔍 Explore Linting vs Formatting:
"I ran Ruff on messy Python code with unused imports, inconsistent spacing, and mixed quotes. The output shows error codes like F401, E501 with [*] markers for some. Explain the difference between formatting and linting, what the error code letters mean (F, E, W, I, N), how Ruff knows which errors are auto-fixable, and the difference between
ruff formatvsruff check."
🧪 Test False Positive Handling:
"Ruff is flagging three scenarios I think are legitimate: a 120-character URL string (E501 line too long), a logging import only used in exception handlers (F401 unused), and intentional mixed quotes for SQL vs Python strings. For each, is it a false positive or valid warning? Show me how to ignore specific rules per-line with
# noqaand how to configure project-wide exceptions in pyproject.toml. When should I ignore vs fix?"
🎯 Practice Code Quality Workflow:
"Create a Ruff workflow for UV projects covering: daily development (when to run format vs check, fixing incrementally, handling disagreements), pre-commit quality gates (command sequence, verification, unfixable errors), and team standards (which error categories to enable, which to ignore for learning projects, using # noqa for exceptions). Include exact commands and expected outputs."
🚀 Integrate with Zed IDE:
"Show me how to set up Ruff in Zed IDE: run formatting automatically on file save, display Ruff errors inline in the editor instead of just terminal, and use quick-fix commands for auto-fixable errors. What's the optimal workflow—fix in editor or terminal?"