Skip to content

Linting & Formatting — ruff and black

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.

Run this in your terminal — no Playground needed for CLI commands.

Terminal window
# Install (add to your project's dev dependencies)
pip install ruff
# or with uv:
uv add --dev ruff
# Lint the whole project
ruff check .
# Auto-fix fixable lint violations
ruff check --fix .
# Format the whole project (replaces black)
ruff format .
# Check formatting without writing (CI mode)
ruff format --check .
TypeScript
// .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
}
Python
# pyproject.toml — one file for everything
[tool.ruff]
line-length = 88
indent-width = 4
[tool.ruff.lint]
# E/W = pycodestyle F = pyflakes I = isort UP = pyupgrade
select = ["E", "F", "I", "UP"]
ignore = ["E501"] # line-too-long (handled by formatter)
[tool.ruff.format]
quote-style = "double" # matches black defaults

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.

Terminal window
pip install black
# Format a single file
black src/main.py
# Format entire project
black .
# Check-only mode for CI
black --check .
TypeScript
# Node / TypeScript workflow
npx eslint src/ --fix
npx prettier src/ --write
# Or with a combined script in package.json:
# "lint:fix": "eslint src/ --fix && prettier src/ --write"
Python
# Python workflow — ruff does both
ruff 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: ruff and black operate on files and require a terminal environment. Run the commands above in your project directory.

Which single tool replaces both flake8 (lint) and black (format) in a modern Python project?
What command formats an entire Python project with ruff without modifying files (CI mode)?
Where does ruff read its configuration from?