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:

print('hello')
def foo( x,y,z ):
return x+y+z

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:

print("hello")


def foo(x, y, z):
return x + y + z

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 13.


Checking for Errors (Linting) (Tier 1: Direct Command)

Formatting makes code look good. Linting finds actual bugs.

Create a file buggy.py:

import os
import sys

print("Hello")

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:

print("Hello")

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, Lesson 9)

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

Use your AI companion for these exercises.

Prompt 1: Install & Run (Tier 1 — Direct)

1. Install Ruff in a uv project: `uv add ruff --dev`
2. Create a messy Python file with inconsistent spacing and quotes
3. Run `uv run ruff format .` and show me the before/after

Show me the exact commands and what the file looks like after formatting.

Expected outcome: Ruff installed, formatting works, you see code cleaned up.

Prompt 2: Find Lint Errors (Tier 1 — Direct)

Create a Python file with:
- Unused import (import os but don't use it)
- A long line (>88 characters)

Run `uv run ruff check .` and show me the errors. What does each error code mean?

Expected outcome: Understand that Ruff catches unused imports (F401) and line length (E501).

Prompt 3: Fix With AI (Tier 2 — AI Assistance)

I have lint errors in my Python file. Run `uv run ruff check .` and show me the errors.
Then run `uv run ruff check . --fix` and explain what changed.
Why can some errors be auto-fixed and others not?

Expected outcome: Understand --fix flag, learn which errors are auto-fixable, see real workflow.


Red Flags to Watch

Problem: "Ruff says E501 (line too long) but I don't know how to fix it"

  • What it means: Your line has >88 characters; Ruff wants it shorter
  • What to do: Break the line into multiple lines (Lesson 9 will cover config for this)
  • For now: Ask AI: "My line is too long: [paste line]. How should I break it up?"

Problem: "uv run ruff says 'command not found'"

  • What it means: You forgot --dev when installing, or didn't run uv add ruff --dev
  • What to do: Run uv add ruff --dev again
  • Key reminder: Always use uv run to execute tools; don't try ruff format directly

Problem: "Ruff formatted my file but changed things I didn't want"

  • What it means: Ruff's defaults don't match your style (happens with quotes, line length)
  • What to do: This is why Lesson 9 teaches configuration. For now, accept Ruff's changes or ask AI to customize rules
  • Normal: This is expected; Lesson 9 fixes it