mathlib Style
Use this skill to make Lean code acceptable for mathlib review. Treat the upstream
guides as the source of truth and use this file as an execution checklist.
Sources:
Progressive Disclosure Workflow
Start narrow, then open only the references needed for the task.
- Triage the change. Identify whether the work is mainly formatting, naming,
documentation, API design, proof maintenance, or lint cleanup.
- Load the minimum reference.
- Unsure which topic applies: read
references/README.md.
- File headers/imports: read
references/style/header-imports.md.
- Declaration/proof layout: read
references/style/declaration-layout.md.
- Tactic proof style: read
references/style/tactic-proofs.md.
- API, normal forms, transparency, deprecation: read
references/style/api-design.md.
- Declaration names: read
references/naming/capitalization.md.
- Theorem-name atoms and symbols: read
references/naming/symbols.md.
- Structural theorem naming: read
references/naming/structural-lemmas.md.
- Module docs: read
references/docs/module-docs.md.
- Declaration doc strings: read
references/docs/docstrings.md.
- Citations and generated docs: read
references/docs/citations-and-sections.md.
- Linter commands and responses: read
references/lint/checks.md.
- Inspect nearby mathlib code. Match local conventions in adjacent files before
introducing a new pattern.
- Apply the relevant checklist below. Prefer small edits and avoid unrelated
refactors.
- Run executable checks. Use the command checklist that matches the repository
and the files touched.
Core Review Checklist
Use this first for every mathlib edit.
- File names are
UpperCamelCase.lean, except rare Zulip-discussed exceptions.
- New mathlib files start with copyright/authors, then
module, then imports,
then a module docstring.
public import and import declarations are grouped separately and kept
alphabetic within each block.
- Lines are at most 100 characters unless there is a compelling local exception.
- Top-level commands and declarations are flush-left, even inside namespaces.
- Use
namespace, section, open, and variable for ownership and scope;
keep broad effects close to the declarations that need them.
- Declaration arguments and return types are explicit enough to read on GitHub.
- Multi-line theorem statements indent continuation lines by 4 spaces; proofs
indent by 2 spaces.
:= by and tactic-mode by stay on the preceding line, never alone.
- Focusing bullets use
· for subgoals.
- Do not use
$; use <|, |>, or parentheses.
- Write anonymous functions with
fun (not λ) and prefer ↦ over =>.
- In
rw/simp, write ← with a following space.
- Avoid empty lines inside declarations; use a short comment if separation matters.
- Do not squeeze terminal
simp unless performance or brittleness requires it.
- Prefer API lemmas over forcing unfolding with
erw or rfl after simp/rw.
- Use
where syntax for structures and instances.
- Add deprecation aliases/messages with
@[deprecated (since := "YYYY-MM-DD")]
when renaming or removing public declarations.
Naming Checklist
- Proofs/theorems/terms of
Prop: snake_case.
Prop, Type, Sort, structures, classes, and inductives: UpperCamelCase.
- Functions are named like their return values.
- Other terms of
Type: lowerCamelCase.
- When an
UpperCamelCase name appears inside a theorem name, lower-camel it
inside the snake_case name, e.g. neZero_iff.
- Declaration names use American English spelling.
- Use mathlib's symbol dictionary:
and, or, iff, ne, le, lt, mem,
union, inter, smul, dvd, iSup, iInf, and so on.
- Name hypotheses with
of in statement order: C_of_A_of_B.
- Use namespace-qualified structural names where appropriate:
.ext, .ext_iff,
.inj, .inj_iff, .rec, .recOn, .induction, .induction_on.
- Predicates normally appear as prefixes, except established suffix families
such as
_injective, _surjective, _mono, _monotone, _strictMono.
Documentation Checklist
- Every file has a module docstring
/-! ... -/ after imports.
- Module docs include a title and summary; add sections only when useful:
Main definitions, Main statements, Notation, Implementation notes,
References, Tags.
- New bibliography entries go in
docs/references.bib; cite with mathlib's
bracket style.
- Every definition and major theorem has a doc string. Lemmas with mathematical
content should usually have one too.
- Doc strings use
/-- ... -/, Markdown, and LaTeX where helpful.
- Complete-sentence doc strings end with periods.
- Named theorems in prose are bold, for example
**Mean Value Theorem**.
- Multi-line declaration doc strings are not indented after the first line.
- Use sectioning comments
/-! ### Section title -/ for generated docs; use
ordinary comments for implementation-only notes.
Executable Checks
Run the narrowest checks that prove the edit. In mathlib itself, prefer:
lake build Mathlib.Path.To.Module
lake exe lint-style
lake exe mk_all
Use lake exe mk_all when adding, deleting, moving, or renaming modules.
For focused declaration linting while editing a Lean file, temporarily add one
of these commands near the end of the file, run the file, then remove it before
committing unless the project intentionally keeps it:
#lint
#lint only docBlame docBlameThm
#list_linters
For downstream projects configured with a Lake lint driver, run:
lake lint
lake test
If lake lint is unavailable downstream, the project likely needs a lintDriver
such as batteries/runLinter; do not add project configuration unless the task
explicitly includes downstream setup.
Lint Response Hints
docBlame: add a doc string to the reported definition.
docBlameThm: add a doc string to a theorem or lemma with reusable
mathematical content.
- Naming lints: rename the declaration and add a deprecation alias if it is public.
- Style lints on whitespace/line endings/unicode: fix the source text rather than
silencing the linter.
- Unused argument or generated-name lints: prefer strengthening the statement,
naming arguments intentionally, or using local conventions over adding
nolint.
- Use
@[nolint ...] only for justified false positives; include a nearby comment
when the reason is not obvious.
Common Anti-Patterns
- Do not introduce a new abstraction just to make a short proof prettier.
- Do not replace a stable terminal
simp with a long squeezed simp only.
- Do not change neighboring naming schemes without checking adjacent files.
- Do not add broad imports when a narrower import builds.
- Do not leave temporary
#check, #eval, #lint, or search commands in PR code.
- Do not use
irreducible to seal an API; prefer structures or explicit lemmas.
- Do not reach for
nonrec unless required; prefer restructuring the declaration.
1---2name: mathlib-style3description: Use when writing or reviewing Lean 4 mathlib code for style, naming, docs, and lint.4---56# mathlib Style78Use this skill to make Lean code acceptable for mathlib review. Treat the upstream9guides as the source of truth and use this file as an execution checklist.1011Sources:12- Style: https://leanprover-community.github.io/contribute/style.html13- Naming: https://leanprover-community.github.io/contribute/naming.html14- Documentation: https://leanprover-community.github.io/contribute/doc.html1516## Progressive Disclosure Workflow1718Start narrow, then open only the references needed for the task.19201. **Triage the change.** Identify whether the work is mainly formatting, naming,21 documentation, API design, proof maintenance, or lint cleanup.222. **Load the minimum reference.**23 - Unsure which topic applies: read `references/README.md`.24 - File headers/imports: read `references/style/header-imports.md`.25 - Declaration/proof layout: read `references/style/declaration-layout.md`.26 - Tactic proof style: read `references/style/tactic-proofs.md`.27 - API, normal forms, transparency, deprecation: read `references/style/api-design.md`.28 - Declaration names: read `references/naming/capitalization.md`.29 - Theorem-name atoms and symbols: read `references/naming/symbols.md`.30 - Structural theorem naming: read `references/naming/structural-lemmas.md`.31 - Module docs: read `references/docs/module-docs.md`.32 - Declaration doc strings: read `references/docs/docstrings.md`.33 - Citations and generated docs: read `references/docs/citations-and-sections.md`.34 - Linter commands and responses: read `references/lint/checks.md`.353. **Inspect nearby mathlib code.** Match local conventions in adjacent files before36 introducing a new pattern.374. **Apply the relevant checklist below.** Prefer small edits and avoid unrelated38 refactors.395. **Run executable checks.** Use the command checklist that matches the repository40 and the files touched.4142## Core Review Checklist4344Use this first for every mathlib edit.4546- File names are `UpperCamelCase.lean`, except rare Zulip-discussed exceptions.47- New mathlib files start with copyright/authors, then `module`, then imports,48 then a module docstring.49- `public import` and `import` declarations are grouped separately and kept50 alphabetic within each block.51- Lines are at most 100 characters unless there is a compelling local exception.52- Top-level commands and declarations are flush-left, even inside namespaces.53- Use `namespace`, `section`, `open`, and `variable` for ownership and scope;54 keep broad effects close to the declarations that need them.55- Declaration arguments and return types are explicit enough to read on GitHub.56- Multi-line theorem statements indent continuation lines by 4 spaces; proofs57 indent by 2 spaces.58- `:= by` and tactic-mode `by` stay on the preceding line, never alone.59- Focusing bullets use `·` for subgoals.60- Do not use `$`; use `<|`, `|>`, or parentheses.61- Write anonymous functions with `fun` (not `λ`) and prefer `↦` over `=>`.62- In `rw`/`simp`, write `← ` with a following space.63- Avoid empty lines inside declarations; use a short comment if separation matters.64- Do not squeeze terminal `simp` unless performance or brittleness requires it.65- Prefer API lemmas over forcing unfolding with `erw` or `rfl` after `simp`/`rw`.66- Use `where` syntax for structures and instances.67- Add deprecation aliases/messages with `@[deprecated (since := "YYYY-MM-DD")]`68 when renaming or removing public declarations.6970## Naming Checklist7172- Proofs/theorems/terms of `Prop`: `snake_case`.73- `Prop`, `Type`, `Sort`, structures, classes, and inductives: `UpperCamelCase`.74- Functions are named like their return values.75- Other terms of `Type`: `lowerCamelCase`.76- When an `UpperCamelCase` name appears inside a theorem name, lower-camel it77 inside the `snake_case` name, e.g. `neZero_iff`.78- Declaration names use American English spelling.79- Use mathlib's symbol dictionary: `and`, `or`, `iff`, `ne`, `le`, `lt`, `mem`,80 `union`, `inter`, `smul`, `dvd`, `iSup`, `iInf`, and so on.81- Name hypotheses with `of` in statement order: `C_of_A_of_B`.82- Use namespace-qualified structural names where appropriate: `.ext`, `.ext_iff`,83 `.inj`, `.inj_iff`, `.rec`, `.recOn`, `.induction`, `.induction_on`.84- Predicates normally appear as prefixes, except established suffix families85 such as `_injective`, `_surjective`, `_mono`, `_monotone`, `_strictMono`.8687## Documentation Checklist8889- Every file has a module docstring `/-! ... -/` after imports.90- Module docs include a title and summary; add sections only when useful:91 `Main definitions`, `Main statements`, `Notation`, `Implementation notes`,92 `References`, `Tags`.93- New bibliography entries go in `docs/references.bib`; cite with mathlib's94 bracket style.95- Every definition and major theorem has a doc string. Lemmas with mathematical96 content should usually have one too.97- Doc strings use `/-- ... -/`, Markdown, and LaTeX where helpful.98- Complete-sentence doc strings end with periods.99- Named theorems in prose are bold, for example `**Mean Value Theorem**`.100- Multi-line declaration doc strings are not indented after the first line.101- Use sectioning comments `/-! ### Section title -/` for generated docs; use102 ordinary comments for implementation-only notes.103104## Executable Checks105106Run the narrowest checks that prove the edit. In mathlib itself, prefer:107108```bash109lake build Mathlib.Path.To.Module110lake exe lint-style111lake exe mk_all112```113114Use `lake exe mk_all` when adding, deleting, moving, or renaming modules.115116For focused declaration linting while editing a Lean file, temporarily add one117of these commands near the end of the file, run the file, then remove it before118committing unless the project intentionally keeps it:119120```lean121#lint122#lint only docBlame docBlameThm123#list_linters124```125126For downstream projects configured with a Lake lint driver, run:127128```bash129lake lint130lake test131```132133If `lake lint` is unavailable downstream, the project likely needs a `lintDriver`134such as `batteries/runLinter`; do not add project configuration unless the task135explicitly includes downstream setup.136137## Lint Response Hints138139- `docBlame`: add a doc string to the reported definition.140- `docBlameThm`: add a doc string to a theorem or lemma with reusable141 mathematical content.142- Naming lints: rename the declaration and add a deprecation alias if it is public.143- Style lints on whitespace/line endings/unicode: fix the source text rather than144 silencing the linter.145- Unused argument or generated-name lints: prefer strengthening the statement,146 naming arguments intentionally, or using local conventions over adding `nolint`.147- Use `@[nolint ...]` only for justified false positives; include a nearby comment148 when the reason is not obvious.149150## Common Anti-Patterns151152- Do not introduce a new abstraction just to make a short proof prettier.153- Do not replace a stable terminal `simp` with a long squeezed `simp only`.154- Do not change neighboring naming schemes without checking adjacent files.155- Do not add broad imports when a narrower import builds.156- Do not leave temporary `#check`, `#eval`, `#lint`, or search commands in PR code.157- Do not use `irreducible` to seal an API; prefer structures or explicit lemmas.158- Do not reach for `nonrec` unless required; prefer restructuring the declaration.