CSLib: The Lean Computer Science Library

Alexandre Rademaker
CSLib Initiative, Renphil | FGV/EMAp
Foundations of AI Seminar Series, Georgia Tech | October 5, 2026
arademaker.github.io/gatech-2026

About me

  • MSc in CS (UFF, 2005): formal methods, rewriting logic in Maude.

  • PhD in CS (PUC-Rio, 2010): proof theory for description logics. Internships at SRI (PVS, 2009) and Microsoft Research, with the Z3 team (2008).

  • IBM Research Brazil (2012–2025): NLP, computational semantics, ontologies.

  • FGV/EMAp, professor since 2010: discrete mathematics, programming, algorithms, type theory, category theory.

  • In the Lean community since March 2015.

What this talk is about

  • The library. What CSLib is, where it stands, how it is governed, how to contribute.

  • The API, concretely. Two worked examples, type-checked against CSLib while this deck was built.

  • The Initiative. What Renaissance Philanthropy supports, and why that is not the same thing as the library.

  • The ecosystem, and AI. Textbooks, courses and verification projects built on CSLib; CSLib as data for AI, and AI as a CSLib contributor.

What is Lean?

Lean logo

lean-lang.org: a proof assistant and programming language that is transforming how we approach mathematics, software verification, and AI.

Lean provides machine-checkable proofs.

Lean addresses the trust bottleneck.

Lean is implemented in Lean, and is very extensible and scalable.

It is based on dependent type theory.

Small trusted kernel. Proofs can be exported and independently checked.

325,000+ unique installations: VS Code (184K) + Open VSX (141K).

This and the next two slides are adapted from the FROCON 2026 deck of Leo de Moura (@leodemoura).

Lean is a "Game"

def odd (n : Nat) : Prop := ∃ k, n = 2 * k + 1 theorem square_of_odd_is_odd : odd n → odd (n * n) := by intro ⟨k₁, e₁⟩ simp [e₁, odd] exists 2 * k₁ * k₁ + 2 * k₁ lia

The "game board": you see goals and hypotheses, then apply "moves" (tactics). Each tactic transforms the game board.

Mathlib: The Lean Mathematical Library

Created in July 2017, in Lean 3 during Big Proof. An open-source, community-driven library. Today:

Mathlib dependency graph

Why a library, and why now

  • AI writes more and more of the world's code. Tests sample inputs; a proof covers all of them.

  • But a proof needs a statement, and a statement needs vocabulary: transition systems, logics, semantics, cost models.

  • CSLib's aim: that vocabulary for computer science, shared, and checked by Lean's kernel.

AI-based provers are bottlenecked by the abstractions available in the underlying proof assistant.

— Barrett et al., CSLib: Towards a Lean Computer Science Library, CACM (forthcoming)

Part 1: The Library

What is CSLib?

An open-source library of reusable components for proving theorems in computer science and writing formally verified code in the Lean programming language and proof assistant.

Two pillars:

  1. Formalizing computer science in Lean. Models of computation, semantics, logics, algorithms and data structures with correctness and complexity proofs.

  2. Reasoning about everyday code. Boole, an intermediate verification language embedded in Lean, as the bridge from mainstream imperative code to CSLib's machinery.

github.com/leanprover/cslib · cslib.io

Why a unified library?

Formal-methods work tends to produce isolated artifacts: a semantics here, a memory model there, a process calculus somewhere else.

The formalizations are designed to form a coherent and integrated framework rather than a collection of unrelated modules.

— Barrett et al., CSLib: Towards a Lean Computer Science Library, CACM (forthcoming)

Mathlib is a dependency:

  • CSLib reuses its mathematics, style guide and linters, and many definitions.

  • The rule: do not rebuild what Mathlib already has.

  • The boundary is not always obvious. Mathlib also has DFA, context-free grammars and graphs, RegularExpressions, etc; all of them, computer science concepts.

How it started

Some independent efforts converged around July, 2025, bringing together Clark Barrett, Swarat Chaudhuri, Jim Grundy (Amazon), Pushmeet Kohli, Fabrizio Montesi and Leonardo de Moura:

  • Clark Barrett and Swarat Chaudhuri were discussing shared infrastructure for formal computer science.

  • Pushmeet Kohli had raised the same idea with Leonardo de Moura (Kevin Hartnett, The Proof in the Code, 2026).

  • Fabrizio Montesi had independently started a cslib repository.

  • Amazon and Google DeepMind funded two technical-lead positions.

  • Renaissance Philanthropy came in to build the Initiative around it.

Supporting organisations listed on cslib.io: Amazon, Google DeepMind, FORM, Renaissance Philanthropy, Stanford Center for Automated Reasoning.

Where it stands today

Fifteen and a half months after the first commit:

Metric

Value

Lean files in Cslib/

253

Non-empty lines

33,727

Theorems and lemmas

2,579

Definitions, structures, classes

1,179

Contributors

57

Merged pull requests

622

GitHub stars / forks

728 / 202

leanprover/cslib main at c149a9d (2026-10-01).

What is in it

Area

Lines

Highlights

Computability

12,319

Automata, Turing machines, URM, circuits, FLP

Foundations

7,836

LTS, bisimulation, relations, monads, data, syntax

Languages

7,004

λ-calculi, F<:, CCS, choreographies, processes

Logics

3,327

Linear, modal, HML, propositional

Crypto

1,423

Perfect secrecy, secret sharing, commitments, PRGs

MachineLearning

872

PAC learning, VC dimension

Algorithms

660

Time monad, sorting, Diffie–Hellman

Probability

251

PMF, statistical distance

Governance

CSLib lives in the leanprover GitHub organisation, next to Lean itself. The steering committee guides the vision and secures support:

  • Clark Barrett (Stanford, Amazon)

  • Swarat Chaudhuri (Google DeepMind, UT Austin)

  • Jim Grundy (Amazon)

  • Pushmeet Kohli (Google DeepMind)

  • Leonardo de Moura (Lean FRO, Amazon)

  • Fabrizio Montesi (FORM, University of Southern Denmark)

Maintainers

The maintainers own the codebase and its technical direction. Lead maintainer: Fabrizio Montesi. Technical leads: Alexandre Rademaker (Logic), Sorrachai Yingchareonthawornchai (Algorithms and data structures).

Area maintainers:

  • Chris Henson (Drexel): λ-calculus, metaprogramming

  • Kim Morrison (Lean FRO): CI/CD with Lean and Mathlib

  • Samuel Schlesinger (Google): Complexity, cryptography, learning theory

  • Christian Reitwiessner: Complexity

  • and the technical leads

New members are invited on project need and merit.

CSLib at FLoC 2026

Two papers, two complementary views of the same library:

  • Computer Science as Infrastructure: the Spine of CSLib. Christopher Henson and Fabrizio Montesi. Founding technical principles, reusable semantic interfaces (reduction and labelled transition systems), proof automation, CI for Mathlib compatibility. arXiv:2602.15078

  • CSLib: The Lean Computer Science Library. Presented by Clark Barrett and Sorrachai Yingchareonthawornchai; the vision paper of the steering committee and technical leads, forthcoming in CACM. arXiv:2602.04846

How to contribute

Depend on it first. That is the fastest way to find what is missing:

[[require]]
name = "cslib"
scope = "leanprover"
rev = "<a commit SHA>"   # pin it: `main` moves fast
  • Most contributions are pull requests, approved by a relevant maintainer.

  • Anything cross-cutting: discuss first, on the #CSLib Zulip channel or an issue.

  • Weekly online meetings

  • The rules are written down: CONTRIBUTING.md (style, documentation, AI use) and DECISION_MAKING.md (how PRs are reviewed and accepted).

How a pull request gets in

From DECISION_MAKING.md:

  • Every PR is reviewed. Anyone may review, and reviewing is a contribution in its own right.

  • Acceptance needs one maintainer's approval, and every substantive part reviewed.

  • An objection blocks the merge until it is resolved, by technical discussion first. If that fails, the Lead Maintainer decides.

  • Reuse over duplication: build on existing definitions, in CSLib or its dependencies, unless an alternative has a clear technical benefit.

Part 2: The API, Concretely

Every Lean block from here on is elaborated against CSLib at 12ba7cf, unless the slide says it is quoting.

The semantic spine

The most reused abstraction in the library: a labelled transition system is just a ternary relation.

structure LTS (State : Type u) (Label : Type v) where /-- The transition relation. -/ Tr : State → Label → State → Prop

A nondeterministic automaton is an LTS with start states:

structure NA (State Symbol : Type*) extends LTS State Symbol where /-- The set of initial states of the automaton. -/ start : Set State

Nondeterministic Turing machines SingleTapeNTM extends NA, with tape actions (read, write, move) as labels.

CSLib authors: Fabrizio Montesi (@fmontesi), Thomas Waring (@thomaskwaring), Ching-Tsun Chou (@ctchou), Chris Henson (@chenson2018)

A tiny nondeterministic automaton

q₀ q₁ a a, b

An NA.FinAcc is an NA (an LTS with start states) plus a set of accepting states. Its instance of Acceptor says when a word is accepted: a multistep transition (MTr) labelled by the word leads from a start state to an accepting state.

instance : Acceptor (FinAcc State Symbol) Symbol where Accepts (a : FinAcc State Symbol) (xs : List Symbol) := ∃ s ∈ a.start, ∃ s' ∈ a.accept, a.MTr s xs s'

language a is the set of words that a accepts.

...in Lean

Words over {a, b} that end in a. On a, state q₀ may stay or move to q₁:

inductive St | q₀ | q₁ def endsInA : NA.FinAcc St Char where Tr s c s' := (s = .q₀ ∧ s' = .q₀) ∨ (s = .q₀ ∧ c = 'a' ∧ s' = .q₁) start := {.q₀} accept := {.q₁} example : ['b', 'a'] ∈ language endsInA := ⟨.q₀, rfl, .q₁, rfl, .stepL (.inl ⟨rfl, rfl⟩) (.stepL (.inr ⟨rfl, rfl, rfl⟩) .refl)⟩ example : ['a', 'b'] ∉ language endsInA := by rintro ⟨_, rfl, _, rfl, h⟩ cases h with | stepL _ h => cases h with | stepL h r => cases r; simp [endsInA] at h

Bisimulation, defined once

def IsBisimulation (lts₁ : LTS State₁ Label) (lts₂ : LTS State₂ Label) (r : State₁ → State₂ → Prop) : Prop := ∀ ⦃s₁ s₂⦄, r s₁ s₂ → ∀ μ, ( (∀ s₁', lts₁.Tr s₁ μ s₁' → ∃ s₂', lts₂.Tr s₂ μ s₂' ∧ r s₁' s₂') ∧ (∀ s₂', lts₂.Tr s₂ μ s₂' → ∃ s₁', lts₁.Tr s₁ μ s₁' ∧ r s₁' s₂') )

Two states are bisimilar, s₁ ~[lts₁, lts₂] s₂, when some bisimulation relates them.

Bisimulation, constructively

Two clocks: one state ticking forever, and two states ticking back and forth. To prove them bisimilar, exhibit a relation, here everything to everything, and check the transfer condition:

inductive C₁ | t₀ inductive C₂ | t₁ | t₂ def one : LTS C₁ Unit := ⟨fun _ _ _ => True⟩ def two : LTS C₂ Unit := ⟨fun s _ s' => s ≠ s'⟩ example : C₁.t₀ ~[one, two] C₂.t₁ := by refine ⟨fun _ _ => True, trivial, ?_⟩ intro _ s₂ _ _ refine ⟨fun _ _ => ?_, fun _ _ => ⟨.t₀, trivial, trivial⟩⟩ cases s₂ · exact ⟨.t₂, by simp [two], trivial⟩ · exact ⟨.t₁, by simp [two], trivial⟩

Two vending machines

Milner, Communication and Concurrency (1989).

  • Good: coin, then you pick tea or coffee. \mathit{Good} \stackrel{\text{def}}{=} \mathit{coin}.(\mathit{tea}.\mathit{Good} + \mathit{coffee}.\mathit{Good})

  • Bad: coin, then the machine picks. \mathit{Bad} \stackrel{\text{def}}{=} \mathit{coin}.\mathit{tea}.\mathit{Bad} + \mathit{coin}.\mathit{coffee}.\mathit{Bad}

Their logs are identical: coin tea, coin coffee, ... Same traces. A trace-based test cannot tell them apart.

After the coin, the bad machine may already have chosen coffee, and then the tea button does nothing. A trace records the actions that happened; it never records an action that was refused.

Example: Jesse Alama (@jessealama). CSLib authors: Fabrizio Montesi (@fmontesi).

Traces are too coarse

Trace equivalence ignores which actions are available at each step.

Bisimilarity (slide 14.4): every move of one machine must be matched by a move of the other, and the states reached must again be related, at every step.

Two ways to prove that our machines are not bisimilar:

  1. Directly, as CSLib's own vm_ltsD_ltsND_not_bisim does: assume a bisimulation and follow the transitions until it breaks.

  2. With a logic: find a formula that one machine satisfies and the other does not.

...in CSLib's CCS

abbrev coin := Act.name "coin" abbrev tea := Act.name "tea" abbrev coffee := Act.name "coffee" inductive Machine | good | bad /-- good = coin.(tea + coffee) bad = coin.tea + coin.coffee -/ @[grind =] def defs : Machine → Option (Process String Machine) | .good => some `(CCS| coin. ((tea. const .good) + (coffee. const .good))) | .bad => some `(CCS| (coin. tea. const .bad) + (coin. coffee. const .bad)) /-- Both machines live in one transition system: CCS's, from CSLib. -/ abbrev machines := CCS.lts (defs := defs)

One LTS, machines, with two constants: the good machine is const .good, the bad one const .bad.

...and its semantics

The transitions of a CCS process are an inductive relation, one rule per construct. CSLib declares it as an LTS with @[lts lts]:

@[lts lts] inductive Tr : Process Name Constant → Act Name → Process Name Constant → Prop where | pre : Tr (pre μ p) μ p | parL : Tr p μ p' → Tr (par p q) μ (par p' q) | parR : Tr q μ q' → Tr (par p q) μ (par p q') | com : μ.Co μ' → Tr p μ p' → Tr q μ' q' → Tr (par p q) Act.τ (par p' q') | choiceL : Tr p μ p' → Tr (choice p q) μ p' | choiceR : Tr q μ q' → Tr (choice p q) μ q' | res : μ ≠ Act.name a → μ ≠ Act.coname a → Tr p μ p' → Tr (res a p) μ (res a p') | const : defs k = some p → Tr p μ p' → Tr (const k) μ p'

Our machines need four rules: pre, choiceL, choiceR, and const, which unfolds a constant through defs.

...as transition graphs

Good tea.Good + coffee.Good coin tea coffee tea.Bad Bad coffee.Bad coin coin tea coffee

Both have the traces coin tea, coin coffee, ... After coin, Good still offers both drinks; Bad has already committed to one.

...not bisimilar, directly

Assume a bisimulation r. After coin, the good machine has a single successor, so r must relate tea.Good + coffee.Good with tea.Bad. Only the first can do coffee:

theorem good_not_bisim_bad_direct : ¬ ((const Machine.good) ~[machines] (const Machine.bad)) := by rintro ⟨r, hr, hb⟩ let p₁ := `(CCS| (tea. const Machine.good) + (coffee. const Machine.good)) let q₁ := `(CCS| tea. const Machine.bad) have hdet : machines.DeterministicStateLabel (const .good) coin := by intro _ _ h₁ h₂ grind [const_tr h₁, const_tr h₂] have h : r p₁ q₁ := match_deterministic hb hr hdet (.const rfl .pre) (.const rfl (.choiceL .pre)) have hpq : p₁ ~[machines] q₁ := ⟨r, h, hb⟩ have hc : machines.Tr p₁ coffee (const .good) := .choiceR .pre grind [hpq.follow_fst]

Hennessy–Milner logic

A modal logic for labelled transition systems. Its formulas describe which actions a state can perform, and what holds after them:

\begin{aligned} s \models \langle a\rangle\,\varphi &\iff \exists s'.\; s \xrightarrow{a} s' \text{ and } s' \models \varphi && \text{some } a \text{ is possible, then } \varphi \\ s \models [a]\,\varphi &\iff \forall s'.\; s \xrightarrow{a} s' \text{ implies } s' \models \varphi && \text{after every } a,\ \varphi \end{aligned}

plus ⊤, ¬ and ∧.

Hennessy–Milner theorem (1985):

  • Bisimilar states satisfy the same formulas.

  • For image-finite systems, the converse holds: states that are not bisimilar are always told apart by some formula.

The first direction is the one we use, as CSLib's bisimulation_satisfies:

lemma bisimulation_satisfies {hrb : m.lts.IsHomBisimulation r} (hv : ∀ {s1 s2}, r s1 s2 → ∀ p, m.v s1 p ↔ m.v s2 p) (hr : r s1 s2) (φ : HML.Proposition Label Atom) : ⇓HML[m,s1 ⊨ φ] ↔ ⇓HML[m,s2 ⊨ φ] := by

CSLib authors: Fabrizio Montesi (@fmontesi), Marco Peressotti (@mperessotti), Alexandre Rademaker (@arademaker).

...one formula, in CSLib's HML

In CSLib, formulas are evaluated in a model, an LTS plus a valuation of atomic propositions (Cslib/Logics/HML/Basic.lean):

structure Model State Label Atom where /-- The labelled transition system. -/ lts : LTS State Label /-- Valuation of atoms at states. -/ v : State → Atom → Prop

Our model m is the CCS LTS of both machines with no atomic propositions (Atom := Empty), so only transitions matter. The formula [coin] ⟨tea⟩ ⊤: after every coin, tea is possible.

/-- No atomic propositions: only the transitions matter. -/ abbrev m : HML.Model (Process String Machine) (Act String) Empty := ⟨machines, fun _ _ => False⟩ /-- "After every coin, tea is on offer." -/ def teaAfterCoin : HML.Proposition (Act String) Empty := d[coin] (d⟨tea⟩ ⊤)

...which the good machine accepts and the bad machine fails

theorem good_ok : ⇓HML[m, const Machine.good ⊨ teaAfterCoin] := by rw [teaAfterCoin, Satisfies.hml_dynBox_iff_forall] rintro s' htr obtain ⟨_, ⟨⟩, ⟨⟩⟩ := const_tr htr exact Satisfies.hml_dynDiamond_intro (Tr.choiceL Tr.pre) (by grind [modal]) theorem bad_fails : ¬ ⇓HML[m, const Machine.bad ⊨ teaAfterCoin] := by rw [teaAfterCoin, Satisfies.hml_dynBox_iff_forall] intro h have := h (pre coffee (const .bad)) (Tr.const rfl (Tr.choiceR Tr.pre)) obtain ⟨_, htr, -⟩ := Satisfies.hml_dynDiamond_iff_exists.mp this grind

In obtain ⟨_, ⟨⟩, ⟨⟩⟩, each ⟨⟩ case-splits a hypothesis and substitutes it away: after one coin, the good machine has a single successor, and the goal is now about that successor.

...and a theorem

theorem good_not_bisim_bad : ¬ ((const Machine.good) ~[machines] (const Machine.bad)) := by rintro ⟨r, hr, hb⟩ grind [bisimulation_satisfies (m := m) (hrb := hb) (by simp) hr teaAfterCoin, good_ok, bad_fails]

So a formula true for one machine and false for the other is a certificate that they are not bisimilar.

Three parts of CSLib in 35 lines

  • A language: CCS, with its operational semantics.

  • A logic: HML, evaluated on that semantics.

  • The semantic infrastructure that connects them: transition systems, bisimulation, the Hennessy–Milner theorem.

Languages produce transition systems. Logics consume them. Metatheory is proved once.

Your program is already a specification

To check that a fast program is correct, we need a specification. Often the simplest program that does the job is that specification: obviously correct, but too slow to use.

  • Specification: insertion sort, six lines, nothing clever.

  • Implementation: CSLib's verified mergeSort, standing in for the optimised version an engineer, or an AI agent, would write.

  • Goal: prove they return the same output on every input, and count how many comparisons each one makes.

Both are written in CSLib's time monad TimeM: a program returns its result together with a cost, and each ✓ charges one comparison.

Example: Jesse Alama (@jessealama). CSLib authors: Sorrachai (@sorrachai), Eric Wieser (@eric-wieser), Kim Morrison (@kim-em).

...the obvious sort

variable {α : Type} [LinearOrder α] def insertSorted (x : α) : List α → TimeM ℕ (List α) | [] => return [x] | y :: ys => do ✓ let c := (x ≤ y : Bool) if c then return x :: y :: ys else return y :: (← insertSorted x ys) def insertionSort : List α → TimeM ℕ (List α) | [] => return [] | x :: xs => do insertSorted x (← insertionSort xs)

...same answer, different bill

#eval ⟪insertionSort [5, 3, 1, 4, 2]⟫
[1, 2, 3, 4, 5]
#eval ⟪mergeSort [5, 3, 1, 4, 2]⟫
[1, 2, 3, 4, 5]
#eval (insertionSort (List.range 1000).reverse).time
499500
#eval (mergeSort (List.range 1000).reverse).time
4932

...connected to Mathlib

⟪p⟫ drops the cost and keeps the result. Without its cost, our insertion sort is Mathlib's List.insertionSort:

@[simp, grind =] theorem ret_insertSorted (x : α) (l : List α) : ⟪insertSorted x l⟫ = l.orderedInsert (· ≤ ·) x := by fun_induction insertSorted with grind @[simp, grind =] theorem ret_insertionSort (xs : List α) : ⟪insertionSort xs⟫ = xs.insertionSort (· ≤ ·) := by fun_induction insertionSort with grind

Why Mathlib's definitions: Mathlib already proves that List.insertionSort returns a sorted permutation of its input. One bridge lemma, and we reuse those proofs instead of redoing them.

Mathlib authors: Jeremy Avigad (@avigad), Wrenna Robson (@wrenna-robson).

...equivalent, for every input

Both outputs are sorted permutations of the input, and a list has only one sorted permutation:

/-- The fast one agrees with the obvious one. Not tested. Proved. -/ theorem mergeSort_eq_insertionSort (xs : List α) : ⟪mergeSort xs⟫ = ⟪insertionSort xs⟫ := by obtain ⟨hs, hp⟩ := mergeSort_correct xs simpa using List.Perm.eq_of_sortedLE hs.sortedLE List.sortedLE_insertionSort (hp.trans (List.perm_insertionSort _ xs).symm)
  • From CSLib: mergeSort_correct, the output of mergeSort is sorted and a permutation of xs.

  • From Mathlib: List.sortedLE_insertionSort and List.perm_insertionSort, the same for insertion sort; and List.Perm.eq_of_sortedLE, two sorted lists that are permutations of each other are equal.

...and the cost of insertionSort is n²

theorem insertSorted_time (x : α) (l : List α) : (insertSorted x l).time ≤ l.length := by fun_induction insertSorted with grind @[simp] theorem insertionSort_length (xs : List α) : ⟪insertionSort xs⟫.length = xs.length := by simp theorem insertionSort_time (xs : List α) : (insertionSort xs).time ≤ xs.length ^ 2 := by fun_induction insertionSort <;> simp grind [insertSorted_time, insertionSort_length]

The mergeSort is n ⌈log₂ n⌉ as proved in CSLib

theorem mergeSort_time (xs : List α) : let n := xs.length (mergeSort xs).time ≤ n * clog 2 n := by grind [mergeSort_time_le, timeMergeSortRec_le]

...and the checker says no

The exact worst case for insertion sort is accepted:

set_option maxRecDepth 4000 in example : (insertionSort (List.range 100).reverse).time = 100 * 99 / 2 := by decide

A false claim about merge sort is refused. Click native_decide for the reason:

example : (mergeSort (List.range 1000).reverse).time = 5000 := by native_decide

Part 3: The CSLib Initiative

Opensource Library ≠ Initiative

The library

The Initiative

leanprover/cslib, open source

A programme at Renaissance Philanthropy

Community-governed; mostly volunteers

A director and a small team

Decides its own technical direction

Helps CSLib growth; does not lead it

Grows organically

Invests where growth won't happen on its own

Modelled on the Mathlib Initiative: a thriving open-source project, paired with a dedicated team for work that is hard to sustain on volunteer effort.

The Initiative's four goals

Goal

What it means

G1: Sustain organic growth

Review workflow, CI and DevOps, documentation

G2: Demonstrate value

Pulling projects; an open AI dataset

G3: Focused technical investment

Boole, semantics, specification logics, RAM model ...

G4: Support community efforts

Software Foundations in Lean, Separation Logic, Signal Shot (BAIF, Crypto)

Pulling projects

The most important idea in the plan:

External formalisation efforts that demand new CSLib primitives and upstream their general results back.

  • They aim at software the world uses every day.

  • Their requirements decide what CSLib builds next.

  • The general pieces they produce come back to the library.

The test they impose: general lemmas must be separable from project code. If that is hard, the API is wrong.

Learning from lean-zip

lean-zip (Kim Morrison): DEFLATE in pure Lean, with a kernel-checked theorem that decompression inverts compression, for every input and every level. About 1,100 theorems, no sorry.

  • Written by AI agents, loosely supervised. Agents claimed issues, worked in their own git worktrees, and opened pull requests.

  • The proof is the gate. A PR could not merge unless the round-trip proof still went through.

  • So optimisation is safe to automate. It ended up faster than Rust's miniz_oxide at the same compression ratio.

For the Initiative: learn from this way of building verified software, and upstream to CSLib whatever is general.

Part 4: CSLib in the Wild

Software Foundations in Lean

Benjamin Pierce (Penn), Michael Hicks (Penn and AWS) and Harry Goldstein (Buffalo) are adapting Software Foundations (also here), the standard introduction to interactive theorem proving, to Lean.

  • Courses that draw on CSLib and contribute back to it.

  • A pipeline from students to library contributors.

  • A planned follow-up course on agentic proof engineering.

Teaching is the maturity test that matters most: it forces the API to be explainable.

A textbook that uses CSLib: FAD

cslib-community/fad: Bird and Gibbons' Algorithm Design with Haskell, in Lean, taught at FGV/EMAp. We are starting to adapt it to Verso and to use CSLib's defs like TimeM:

def maxM (x y : ℕ) : TimeM ℕ ℕ := do ✓ pure (max x y) def maximumM : List ℕ → TimeM ℕ ℕ | [] => pure 0 | [x] => pure x | x :: y :: ys => do maxM x (← maximumM (y :: ys)) /-- The maximum of `n` numbers takes `n - 1` comparisons. -/ theorem time_maximum (xs : List ℕ) : (maximumM xs).time = xs.length - 1 := by fun_induction maximumM <;> simp_all [maxM]

Beyond TimeM, two open proposals for a query-complexity model, #401 (Kim Morrison) and #685 (Shreyas Srinivas), derive costs from the operations a program performs: useful for amortised running times (ADwH §2.4).

A course book in progress: CSwL

Computational Semantics with Lean (repo) brings van Eijck and Unger's Computational Semantics with Functional Programming from Haskell to Lean, while the FGV/EMAp course runs.

  • Now: stay close to the book, the safe route while students follow it.

  • Next weeks: reuse what is already mapped: grammars, propositional and modal logic, LTS.

  • Then: contribute what CSLib lacks: first-order logic, feature structures and their unification.

With Software Foundations in Lean and FAD: CSLib as a base for teaching.

s2n-bignum in Lean

  • Amazon's s2n-bignum: integer arithmetic routines for cryptography, in x86-64 and AArch64 machine code. Correctness and constant-time execution are verified in HOL Light, with a purpose-built relational Hoare logic.

  • cslib-community/bignum: a faithful port of that logic to Lean 4, including its lenses (components). The aim: verify other critical machine code in Lean, possibly with AI-assisted proofs.

  • Two of s2n-bignum's ten ARM tutorials (simple, sequence) already run in Lean, on the first model, while the architecture is being rewritten.

bignum: Guilherme Lima (@gflima), Alexandre Rademaker (@arademaker).

...components are lenses

A component is a lens on one part of the machine state: a way to read it and a way to write it.

structure Component (α : Type u₁) (β : Type u₂) where /-- Reader function. -/ read : α → β /-- Writer function. -/ write : β → α → α

XREG n is register n: (XREG n).read s reads it in state s, and (XREG n).write 0xabc s returns s with 0xabc in register n.

/-- Main integer registers. -/ def XREG (n : Nat) : Component State (BitVec 64) := if n ≥ 31 then XZR else registers :> .element n

...and instructions are generic

def ADD {α : Type u} {w : Nat} (Rd : Component α (BitVec w)) (Rm : Component α (BitVec w)) (Rn : Component α (BitVec w)) (s : α) : α → Prop := let m := Rm.read s let n := Rn.read s let d : BitVec w := m + n (Rd ≔ d) s

Rd, Rm and Rn are components passed as arguments, not specific registers. The same ADD, unchanged, gives:

  • ADD X0 X1 X2: 64-bit registers

  • ADD W0 W1 W2: 32-bit registers

  • ADD X0 (X1.shifted LSL 1) (.rvalue 0x33): a shifted register and a literal

No separate version for shifts, literals or 32 bits; the same holds for most other instructions.

The community organisation

github.com/cslib-community: home for community projects built with, around, and for CSLib.

  • fad: functional algorithm design.

  • CSwL: computational semantics.

  • bignum: s2n-bignum in Lean.

  • AlgoLib: graph algorithms, flows, union–find, with correctness and running-time proofs.

Where projects live before anything is upstreamed.

Part 5: CSLib for AI, and with AI

For AI

The ideal outcome would be a "flywheel" in which both AI and human experts become progressively more efficient at producing new knowledge.

— Barrett et al., CSLib: Towards a Lean Computer Science Library, CACM (forthcoming)

  • CSLib as vocabulary: definitions an AI can state specifications in.

  • CSLib as data: a planned regular dataset of goal states, tactic traces and cost annotations, in Mathlib's format.

  • The kernel as the gate: RL agents find every shortcut; the kernel is the one thing they cannot fake.

With AI

  • CSLib ships an AGENTS.md: build, lint and test instructions for coding agents.

  • It follows Mathlib's disclosure rule:

If you use artificial intelligence ... please explain this in the PR description. Explain which tool(s) you used and how you used it.

  • Two reports from this year:

    • July, on Zulip: a proof about η-reduction and strong normalisation, invented by Claude and checked with Aristotle, found in no paper or textbook (#860).

    • September, cut elimination for linear logic: AI agents that "until recently failed badly" now carry out the proof; the library itself has grown enough "to give useful context".

The open question

Not whether AI writes Lean. What a library has to look like for AI-written contributions to be reviewable.

  • Specifications humans can read.

  • Small, stable interfaces that proofs can target.

  • Review that scales with volume.

The community is discussing how humans and agents should coordinate. One idea on the table: blueprints written by humans, stating the intent that both people and agents then work toward.

Getting involved

  • Depend on CSLib in your project, and tell us what is missing.

  • Bring a pulling project.

  • Review a PR, or join the weekly meeting.

  • Say hello on the #CSLib channel of the Lean Zulip.

Thank You

Alexandre Rademaker

CSLib Initiative, Renaissance Philanthropy · FGV/EMAp

cslib.io · github.com/leanprover/cslib

Further reading: Barrett et al., CSLib: Towards a Lean Computer Science Library (CACM, forthcoming; arXiv:2602.04846). Henson and Montesi, Computer Science as Infrastructure (FLoC 2026; arXiv:2602.15078).

alexandre.rademaker@renphil.org