Write Lean Code
Core Principles
- Type-driven development: let the type system guide implementation; express invariants in types
- Leverage Mathlib: use existing theorems, definitions, and tactics before building from scratch
- Tactic proofs for incremental feedback: prefer tactic mode for complex proofs; use the VS Code infoview for step-by-step development
- Clarity and composability: write small, focused lemmas; name them to be discoverable via
exact? and apply?
Workflow
- In a fresh clone or worktree, run the project's documented bootstrap script before any direct
lake build. Mathlib must come from lake exe cache get (prebuilt artifacts), not a local source compilation.
- After bootstrap has succeeded in the current worktree, run
lake build <Module.Name> to check compilation; run project linters if available.
- Update the tests in the same change as the proof code if the project has a test suite that mirrors the proof code. Whenever you add, rename, restate, or delete anything on a module's public surface, update the matching test file in the same change. Treat the test suite as part of the proof code, not an optional extra. For the compile-time,
example-based regression style those test modules typically use (import discipline, 1:1 naming mirror, composition per milestone, anti-patterns), invoke the companion write-lean-tests skill; references/comprehensive/build-infrastructure.md covers the testDriver / defaultTargets wiring side.
- Before declaring a proof change finished, run the project's full local check (build + tests + any proof-boundary or lint checks the project defines).
- Review against essential checklist:
references/essential/checklist.md
- For specific questions, consult:
references/comprehensive/{topic}.md
Project-Local Caveats
Each project using this skill should document its own bootstrap script, test-mirroring convention, namespace rules, and any vendored Lean dependencies that must be excluded from style searches. Read the invoking project's CLAUDE.md (or equivalent agent-config file) for those specifics before applying the generic guidance below.
Vendored Lean dependencies are not style references. When a project pulls in a third-party Lean library through lake (under .lake/packages/<name>/ or the equivalent), that code is a build artifact, not a reference for Lean naming, proof style, tactic preferences, comment or docstring format, file structure, or math prose. Exclude such paths from grep-for-conventions searches. The invoking project's CLAUDE.md should name the specific packages to exclude.
Valid Lean references, in priority order: (1) the project's own code, (2) Mathlib under the project's Mathlib package path (search for both theorem and lemma declarations -- Mathlib uses both), (3) Lean core, and (4) the published documentation linked in the Sources section below.
Mathlib build policy: never use lake build as the first command in a clean worktree or clone. The supported bootstrap path runs lake update, downloads prebuilt Mathlib artifacts with lake exe cache get, verifies those artifacts exist, and only then builds the local libraries. If Mathlib artifacts are missing, rerun the project's bootstrap script rather than letting Lake compile Mathlib from source.
Reference Navigation
Quick reviews (default):
references/essential/checklist.md: condensed, actionable rules
Deep dives by topic:
references/comprehensive/naming.md: identifiers, types, lemmas, files, Mathlib naming scheme
references/comprehensive/style-and-formatting.md: indentation, imports, operators, sections
references/comprehensive/proof-style.md: tactic vs term mode, structured proofs, automation, exploration tactics
references/comprehensive/mathlib.md: documentation (module docstrings, tactic docs, citations, linting), variable conventions, API design, heartbeats
references/comprehensive/mathlib-api-discovery.md: finding lemmas, navigating the module hierarchy, search strategies, common lookup patterns
references/comprehensive/general-programming.md: type classes, monads, pattern matching, dependent types, IO, lake
references/comprehensive/build-infrastructure.md: bootstrap script, Makefile target set, lintDriver, entrypoint manifest, testDriver vs defaultTargets, and test-library discipline for Mathlib-downstream projects
references/comprehensive/pfr-downstream.md: finite-alphabet specialization, noncomputable def + volume_tac, measurability hygiene, and anonymous-constructor pair notation for projects built on PFR's entropy API
references/comprehensive/metaprogramming.md: macros, custom tactics, syntax, elaboration, monad hierarchy
Sources
1---2name: write-lean-code3description: Lean 4 style guide and Mathlib conventions. Use whenever Lean code is the subject of the work, not only when editing: (1) writing, editing, or reviewing .lean files, (2) reading Lean source to answer a user question about it, (3) planning, proposing, or naming lemmas, definitions, theorems, or tactics before implementation, (4) discussing Lean design decisions, refactors, API choices, or proof strategies, (5) summarizing proof status or reporting on formalization progress, (6) writing or editing Lean docstrings and comments, (7) formalizing mathematical proofs, (8) writing custom tactics or metaprograms. Applies to any touch on .lean files or the proofs/ directory, including reading and discussion, not just edits. Covers naming, formatting, proof style, Mathlib conventions, general functional programming, and metaprogramming.4---56# Write Lean Code78## Core Principles9101. **Type-driven development**: let the type system guide implementation; express invariants in types111. **Leverage Mathlib**: use existing theorems, definitions, and tactics before building from scratch121. **Tactic proofs for incremental feedback**: prefer tactic mode for complex proofs; use the VS Code infoview for step-by-step development131. **Clarity and composability**: write small, focused lemmas; name them to be discoverable via `exact?` and `apply?`1415## Workflow16171. In a fresh clone or worktree, run the project's documented bootstrap script before any direct `lake build`. Mathlib must come from `lake exe cache get` (prebuilt artifacts), not a local source compilation.181. After bootstrap has succeeded in the current worktree, run `lake build <Module.Name>` to check compilation; run project linters if available.191. **Update the tests in the same change as the proof code** if the project has a test suite that mirrors the proof code. Whenever you add, rename, restate, or delete anything on a module's public surface, update the matching test file in the same change. Treat the test suite as part of the proof code, not an optional extra. For the compile-time, `example`-based regression style those test modules typically use (import discipline, 1:1 naming mirror, composition per milestone, anti-patterns), invoke the companion `write-lean-tests` skill; `references/comprehensive/build-infrastructure.md` covers the `testDriver` / `defaultTargets` wiring side.201. Before declaring a proof change finished, run the project's full local check (build + tests + any proof-boundary or lint checks the project defines).211. Review against essential checklist: `references/essential/checklist.md`221. For specific questions, consult: `references/comprehensive/{topic}.md`2324## Project-Local Caveats2526Each project using this skill should document its own bootstrap script, test-mirroring convention, namespace rules, and any vendored Lean dependencies that must be excluded from style searches. Read the invoking project's CLAUDE.md (or equivalent agent-config file) for those specifics before applying the generic guidance below.2728**Vendored Lean dependencies are not style references.** When a project pulls in a third-party Lean library through `lake` (under `.lake/packages/<name>/` or the equivalent), that code is a build artifact, not a reference for Lean naming, proof style, tactic preferences, comment or docstring format, file structure, or math prose. Exclude such paths from grep-for-conventions searches. The invoking project's CLAUDE.md should name the specific packages to exclude.2930Valid Lean references, in priority order: (1) the project's own code, (2) Mathlib under the project's Mathlib package path (search for both `theorem` and `lemma` declarations -- Mathlib uses both), (3) Lean core, and (4) the published documentation linked in the Sources section below.3132**Mathlib build policy:** never use `lake build` as the first command in a clean worktree or clone. The supported bootstrap path runs `lake update`, downloads prebuilt Mathlib artifacts with `lake exe cache get`, verifies those artifacts exist, and only then builds the local libraries. If Mathlib artifacts are missing, rerun the project's bootstrap script rather than letting Lake compile Mathlib from source.3334## Reference Navigation3536**Quick reviews (default):**3738- `references/essential/checklist.md`: condensed, actionable rules3940**Deep dives by topic:**4142- `references/comprehensive/naming.md`: identifiers, types, lemmas, files, Mathlib naming scheme43- `references/comprehensive/style-and-formatting.md`: indentation, imports, operators, sections44- `references/comprehensive/proof-style.md`: tactic vs term mode, structured proofs, automation, exploration tactics45- `references/comprehensive/mathlib.md`: documentation (module docstrings, tactic docs, citations, linting), variable conventions, API design, heartbeats46- `references/comprehensive/mathlib-api-discovery.md`: finding lemmas, navigating the module hierarchy, search strategies, common lookup patterns47- `references/comprehensive/general-programming.md`: type classes, monads, pattern matching, dependent types, IO, `lake`48- `references/comprehensive/build-infrastructure.md`: bootstrap script, Makefile target set, `lintDriver`, entrypoint manifest, `testDriver` vs `defaultTargets`, and test-library discipline for Mathlib-downstream projects49- `references/comprehensive/pfr-downstream.md`: finite-alphabet specialization, `noncomputable def` + `volume_tac`, measurability hygiene, and anonymous-constructor pair notation for projects built on PFR's entropy API50- `references/comprehensive/metaprogramming.md`: macros, custom tactics, syntax, elaboration, monad hierarchy5152## Sources5354- [Lean 4 Language Reference](https://lean-lang.org/doc/reference/latest/)55- [Lean 4 Naming Conventions](https://github.com/leanprover/lean4/blob/master/doc/std/naming.md)56- [Mathlib Library Style Guidelines](https://leanprover-community.github.io/contribute/style.html)57- [Mathlib Naming Conventions](https://leanprover-community.github.io/contribute/naming.html)58- [Mathlib Documentation Guidelines](https://leanprover-community.github.io/contribute/doc.html)59- [Mathematics in Lean](https://leanprover-community.github.io/mathematics_in_lean/)60- [Functional Programming in Lean](https://lean-lang.org/functional_programming_in_lean/)61- [Theorem Proving in Lean 4](https://lean-lang.org/theorem_proving_in_lean4/)62- [Metaprogramming in Lean 4](https://leanprover-community.github.io/lean4-metaprogramming-book/)