codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›tools

Linting and formatting

Published 2026-04-28· Updated 2026-05-18·0 views

Linting and formatting

Linters and formatters look similar but play different roles. This article covers the definition of each, the leading tools, and the trade-offs.

1. About linters and formatters

A linter statically inspects code for meaning, style, and potential defects. Diagnostics like "this variable is declared but never used" or "this function calls async without await". The name traces back to lint, a C analyzer Stephen Johnson built at Bell Labs in 1978.

A formatter rewrites code style (indentation, line breaks, whitespace) to be consistent. It does not change meaning. Prettier's official page calls itself "an opinionated code formatter" and intentionally minimizes options. Fewer options is a design decision that lowers consensus cost.

The two roles can be split, or a single tool can do both.

2. JS / TS

Tool First release Role
ESLint 2013 Started by Nicholas C. Zakas. AST-based linter. Plugin ecosystem.
Prettier 2017 James Long. Opinionated formatter.
TypeScript ESLint 2019 typescript-eslint.io. Runs ESLint rules on the TS AST.
Rome → Biome 2023 After the Rome project shut down, the community fork Biome launched. Rust-based. Combines formatter and linter.
dprint 2020 Rust-based formatter. Multi-language plugins.
Oxlint / oxc 2023 Rust-based ESLint-compatible linter. Speed-focused.

Two common combos:

  1. ESLint + Prettier — The biggest ecosystem. Rule conflicts are turned off via eslint-config-prettier. ESLint's plugin breadth (React Hooks, Next.js, Tailwind, security, etc.) is the strength.
  2. Biome alone — Bundles formatter and linter into one binary, fast because it's Rust. Biome's official page reports about 97% Prettier compatibility and roughly 35x speed. It hasn't ported every ESLint rule (currently around 491), so check before switching if specific plugins are critical.

3. Python

Tool First release Role
pylint 2003 The oldest Python linter. Wide checks, on the slower side.
flake8 2010 Wraps pycodestyle + pyflakes + mccabe.
isort 2013 Timothy Crosley. Specialist import sorter.
Black 2018 A PSF project. Opinionated formatter (almost no options).
Ruff 2022 Astral. Rust. Absorbs many flake8 / isort / pydocstyle / pyupgrade / autoflake rules into one tool. Later added Ruff Format (2023) for Black-compatible formatting.

The Ruff docs cite "10–100x faster". A single binary, pyproject.toml config, and auto-fix (--fix) accelerated adoption.

4. Java

Tool Released Role
Checkstyle 2001 Style and convention checks. The oldest.
PMD 2002 Static analysis. Code smells, complexity.
SpotBugs (FindBugs successor) 2017 Bytecode-based latent bug detection.
google-java-format 2015 Formatter for the Google style guide.
Spotless 2016 Gradle / Maven plugin. Integrates formatters into the build phase.

Spotless is often picked for build integration. A single ./gradlew spotlessApply formats everything.

5. pre-commit hook integration

  • lint-staged (Node) + Husky — Runs ESLint / Prettier only on staged JS / TS files. Quick on small PRs.
  • pre-commit (pre-commit.com) — Multi-language. List tools like Ruff, Black, Checkstyle in .pre-commit-config.yaml.
  • lefthook (Go) — Single binary, language-agnostic.

6. Common shapes

ESLint (flat config, v9+):

// eslint.config.mjs
import js from "@eslint/js";
import tseslint from "typescript-eslint";

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  { rules: { "no-console": "warn" } },
];

Prettier:

// .prettierrc
{ "semi": true, "singleQuote": true, "trailingComma": "all", "printWidth": 100 }

Biome:

// biome.json
{
  "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json",
  "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2 },
  "linter": { "enabled": true, "rules": { "recommended": true } }
}

Ruff (pyproject.toml):

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
ignore = []

Commands:

# Common
pnpm exec eslint .
pnpm exec prettier --write .
pnpm exec biome check --write .

# Python
uv run ruff check .
uv run ruff format .

# Java
./gradlew spotlessCheck
./gradlew spotlessApply

7. Trade-offs

Biome vs ESLint + Prettier:

Axis ESLint + Prettier Biome
Config simplicity Two tools each + conflict-avoidance config One file
Speed Sufficient, but slows on large repos Rust-based, reportedly fast
Rule coverage Thousands of rules including plugins About 491 (growing)
Ecosystem maturity 10+ years Relatively new

For large existing codebases with heavy ESLint plugin dependence, switching costs are high. For new projects or simpler rule needs, Biome's single binary lowers consensus cost.

8. Common pitfalls

Formatter and linter colliding on the same rule — let the formatter own formatting and keep the linter on semantic checks. eslint-config-prettier standardizes that split.

Moving to ESLint 9's flat config (eslint.config.js) breaks compatibility with the older .eslintrc.*. Mixing both leaves one side ignored.

Black vs Ruff Format — the line-break decisions are nearly identical but not perfectly aligned. Pick one within a repo and stay consistent.

IDE auto-format vs CI format check on different versions — endless format-only diffs land on every PR. Pin versions in lockfile, package.json, and pyproject.toml.

Too many pre-commit hooks — bypassing (--no-verify) creeps in. Move heavy checks to CI.

Closing thoughts

The split between linter and formatter coexists with the single-binary trend (Biome, Ruff). With heavy ecosystem dependence, ESLint + Prettier; for new projects or speed-driven needs, Biome / Ruff. Either way, pinned versions, editor auto-apply, and CI verification together remove format noise from PRs.

Next

  • python-venv-poetry-history
  • regex

References include ESLint docs, Prettier docs, Biome, Ruff docs, Black docs, Spotless GitHub, typescript-eslint, editorconfig.org, and Prettier — Why Prettier?.

More in tools

All in this category →
  • Git Submodule · Subtree · LFS — repos inside repos
  • Regular expressions — finding strings by pattern
  • A history of Python dependency tools
  • Editor setup
  • Gradle
  • Git workflow