Linting & Formatting — ruff and black
eslint + prettier → ruff
Section titled “eslint + prettier → ruff”In the TypeScript world you configure two tools: eslint enforces code quality rules and prettier enforces style. They have separate configs, separate CLI commands, and occasionally conflict with each other.
Python developers historically used the same split: flake8 (lint) + black (format). But ruff — released in 2022 and written in Rust — now replaces both. One tool, one config section in pyproject.toml, and it runs in milliseconds on an entire codebase.
Installing and running
Section titled “Installing and running”Run this in your terminal — no Playground needed for CLI commands.
# Install (add to your project's dev dependencies)pip install ruff# or with uv:uv add --dev ruff
# Lint the whole projectruff check .
# Auto-fix fixable lint violationsruff check --fix .
# Format the whole project (replaces black)ruff format .
# Check formatting without writing (CI mode)ruff format --check .Configuring ruff vs eslint
Section titled “Configuring ruff vs eslint”// .eslintrc.js (or eslint.config.js)module.exports = { parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint'], rules: { 'no-unused-vars': 'error', '@typescript-eslint/no-explicit-any': 'warn', },};
// .prettierrc{ "singleQuote": true, "semi": false, "printWidth": 88}# pyproject.toml — one file for everything[tool.ruff]line-length = 88indent-width = 4
[tool.ruff.lint]# E/W = pycodestyle F = pyflakes I = isort UP = pyupgradeselect = ["E", "F", "I", "UP"]ignore = ["E501"] # line-too-long (handled by formatter)
[tool.ruff.format]quote-style = "double" # matches black defaultsblack — the opinionated formatter
Section titled “black — the opinionated formatter”Before ruff format existed, black was the de-facto standard. You will see it everywhere in existing Python projects. It is deliberately opinionated — it offers almost no configuration — exactly like prettier with --no-semi locked on. If you inherit a project using black, keep using it; don’t mix.
pip install black
# Format a single fileblack src/main.py
# Format entire projectblack .
# Check-only mode for CIblack --check .The migration story
Section titled “The migration story”# Node / TypeScript workflownpx eslint src/ --fixnpx prettier src/ --write
# Or with a combined script in package.json:# "lint:fix": "eslint src/ --fix && prettier src/ --write"# Python workflow — ruff does bothruff check --fix .ruff format .
# Or in one shot (check then format):ruff check --fix . && ruff format .
# Makefile target (common pattern):# lint:# ruff check --fix . && ruff format .Playground note:
ruffandblackoperate on files and require a terminal environment. Run the commands above in your project directory.