Skip to main content

Ruff Linter & Formatter Basics

The Too-Many-Tools Problem

Before Ruff, Python developers needed three separate tools to write clean code:

ToolJobProblem
BlackFormat code styleOpinionated; no configuration
isortSort imports alphabeticallyDoes only one thing
Flake8Find code errors and style violationsSlow

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=1 becomes x = 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 def and 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 os but never used it
  • You imported sys but 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:

CodeMeaningFixable?
F401Import not usedYes
E501Line too longNo (just warns)
E225Missing whitespace around operatorYes
F841Variable assigned but not usedYes
E203Whitespace before colonYes

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 format vs ruff 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 # noqa and 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?"