Agent skill

Lean Rc Linearity

by leanprover in leanprover/con-leche

Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps

Apache-2.0Auto-check: notesDevelopment

Install Lean Rc Linearity

skills CLI
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install leanprover/con-leche lean-rc-linearity --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .claude/skills/lean-rc-linearity && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
lean-rc-linearity
GitHub stars
122
Token cost
~4.3k tokens
SKILL.md length
2,336 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
Apache-2.0

At a glance

Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps

  • Works in 8 steps: The one rule → Rules first (apply these while writing) → Mechanics (enough to reason from) → …
  • Tasks that involve Project scaffolding
  • SKILL.md covers 0. The one rule, 1. Rules first (apply these…, 2. Mechanics (enough to reason… and 3. The three-and-a-half RC-2…, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Lean Rc Linearity is an agent skill from leanprover/con-leche. Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps

Its SKILL.md is about 4.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering Project scaffolding. The repository describes itself as: An external lean checker with a proof of consistency. The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve Project scaffolding

Example prompts

  • “/lean-rc-linearity”

Requirements

  • Pre-approved tools (allowed-tools): Read, Bash, Grep

Workflow steps

8 steps, taken from the step headings in SKILL.md.

  1. The one rule
  2. Rules first (apply these while writing)
  3. Mechanics (enough to reason from)
  4. The three-and-a-half RC-2 holder incidents in this repo
  5. Diagnosis toolkit
  6. Two structural arguments that buy linearity for free
  7. Codegen landmines (Nat arithmetic and initialization)
  8. Checklist before landing a hot-path change

What it can do on your machine

Read from SKILL.md and the folder at commit 67f0463. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Read
    • Bash
    • Grep

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are c).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • lean-lang.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Lean Rc Linearity loads about 4.3k tokens when it runs. Until then it costs about 35 tokens; SKILL.md has 2,336 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~35
When it runs · the whole SKILL.md, loaded when a task matches
~4.3k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Read, Bash, Grep

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from leanprover/con-leche at commit 67f0463, republished under its Apache-2.0 licence (© leanprover). 2,336 words, ~4,331 tokens.

Download SKILL.mdSave it as .claude/skills/lean-rc-linearity/SKILL.md (or your agent's skills folder).
name
lean-rc-linearity
description
Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps
allowed-tools
Read, Bash, Grep

Lean 4 reference counting and linearity

Canonical source: https://lean-lang.org/doc/reference/latest/Run-Time-Code/Reference-Counting/. Runtime background distilled from Henrik Böving, Everything You Need To Know About The Lean Runtime (Lean FRO offsite, 2026-05-18). Project findings cite DESIGN.md sections and commits in this repo; toolchain evidence is lean.h at v4.33.0.

0. The one rule

An in-place update happens iff the object is at RC 1 at the moment of the mutation. Anything alive across that moment — a variable the compiler chose to keep live, a closure that captured it, a tuple the loop is threading — is a second reference, so the mutation copies the whole structure instead.

Corollary that costs the most time to learn: compiler liveness placement decides this, not source order. Every RC-2 holder found in this project was a compiler-liveness surprise, invisible in the source. Reason about it, then measure it (§4).

1. Rules first (apply these while writing)

  1. Use-then-consume. Every use of a value must finish before the mutation that consumes it. If a rare branch needs the pre-mutation value, decide the branch before the expensive step, don't straddle it. (DESIGN.md "FEnv linearity", §3.4.)
  2. No for/mut loops over threaded state on a hot path. Compiled forIn boxes the accumulator tuple and keeps the previous iteration live into the next step call. Use explicit tail recursion with the accumulators as plain arguments. (progressLoop/diagLoop/parseExportStream in Main.lean, ConLeche/Frontend/Export.lean.)
  3. modify, not get/set. let s ← get; let s := f s; set s leaves the ref holding its own copy while you mutate; modify f hands ownership through. The VEIR parser went 22 s → 4.5 s on exactly this change (getContext/setContext → modifyContext).
  4. One-shot container ops, not read-modify-write. HashMap.alter over getD + insert; Array.modify/set over read-then-write.
  5. State reads that cross a call must be opaque. A read helper that inlines to a pure projection can be sunk past a later call, keeping the projected value alive across it. Mark it @[noinline] (§3.1).
  6. Closure capture is an owned reference for the closure's whole lifetime. Building ops fe (a record of closures over fe) and passing it to a long call pins fe for the duration of that call, even though the source "just passes a parameter" (§3.4).
  7. Borrow read-only parameters. @& (or inferred borrowing) elides RC on traversals entirely (§2.3).
  8. Prefer a phase that returns only Bool. It provably cannot retain anything it built (§5.2).

2. Mechanics (enough to reason from)

2.1 Object model

Every heap object starts with an 8-byte header:

c
typedef struct { int m_rc; unsigned m_cs_sz:16; unsigned m_other:8; unsigned m_tag:8; } lean_object;

m_rc: > 0 single-threaded, = 1 unique, = 0 persistent, < 0 multi-threaded (atomic RC). m_tag is 8 bits → at most 256 constructors. Every indirection costs ≥ 8 bytes, which is why flattening nested structs into scalar fields is a real memory win (leanprover/lean4#11162: ~1 GB off Mathlib's language server by inlining Lsp.Range/Position into Nat fields).

Representations: enum inductives → unboxed integers; single-ctor single-field inductives → that field; everything else lean_ctor_object; Array → lean_array_object; ByteArray/FloatArray → lean_sarray_object; UIntN/USize → native ints; Float32/Float → float/double; Nat/Int → tagged scalar or boxed MPZ.

Boxing when an unboxed value is passed where a lean_object* is expected: UInt8/16/32 → tagged ((n << 1) | 1); UInt64/USize/floats → a single-field ctor allocation; Nat/Int → tagged while small, MPZ otherwise. Chains like n.toNat.toUInt64 pay this repeatedly; a struct of UInt64 fields beats a polymorphic Prod'.

2.2 In-place update and reuse

Array/ByteArray always update in place at RC 1; lean_ctor_object when the compiler decides to. Reuse: when the optimizer sees x will be dec-ed and then an object of the same layout allocated, it emits a runtime uniqueness check and reuses x's memory instead of hitting the allocator.

2.3 The RC ABI

Three argument kinds:

  • scalar (uint8, tagged) — never RC-ed;
  • owned (x : obj) — the callee must dec it;
  • borrowed (x : @& obj) — the caller stays responsible.

Insertion is then forced: inc x when passing x as owned while still using it later; dec x once x is dead, owned and not transferred. A parameter is inferred borrowed if it is only read from, only passed on as borrowed, and never used in reuse — and modern Lean lets you write @& on ordinary functions, not just @[extern]. Marking a recursive read-only traversal @&Node α β → … removes the RC traffic from the whole walk.

Avoiding RC matters beyond the counter bump: it adds code size, adds "is it mt?" branches, and LLVM refuses to optimize across atomics (it will not prove *x still reads 42 after an atomic_fetch_add on an unrelated pointer).

2.4 Compiler knobs you will actually reach for
  • Inlining is annotation-driven (auto-inline only below compiler.small, default 1): @[inline]/@[always_inline], @[macro_inline] (parameters treated lazily — fixes control-flow helpers like a custom ite), @[noinline], and inline (f x) at a call site.
  • Specialization: type classes specialize by default; @[specialize], @[specialize f], @[nospecialize], @[weak_specialize] (for Inhabited-style classes that should ride along only). Inner let rec go loops usually need an explicit @[specialize] to escape closure/vtable passing.
  • Tracing: trace.Compiler (everything), trace.Compiler.saveBase / saveImpure (end-of-phase IR), trace.Compiler.simp, trace.Compiler.result, plus pp.funBinderTypes / pp.letVarTypes. (trace.compiler.ir.result is gone.)
2.5 Concurrency notes (rarely relevant here, but sharp)

Putting a value into Std.Mutex, IO.Ref or Std.Channel marks it multi-threaded → atomic RC forever after. IO.Ref is a TAS spinlock: for real multi-threading use Std.Mutex. Blocking inside IO.asTask does not context-switch and stalls the pool — use Async/Async.sleep. Prefer bounded channels.

3. The three-and-a-half RC-2 holder incidents in this repo

All four have the same shape: a value stayed live across a mutation site because of where the compiler placed liveness, not because the source shared it. Retention across a mutation = inc = copy at that site.

3.1 Sunk pure store reads → @[noinline] withStore

withStore f inlined to the pure application f s.store. When the result was not consumed before the next call, the compiler sank the application past that call (profitable when the call can throw) — e.g. inferBodyI computed getAppArgsI only after r.infer returned, keeping the projected EStore at RC 2 across the entire nested inference. ~6100 whole-table copies per run; ~35 % of the init-prelude probe. Fix: withStore is @[noinline] — an opaque state-threading call cannot be reordered, so the projection lives and dies inside the callee. (ConLeche/Kernel/CoreI.lean:279-291; DESIGN.md "The whole-arena copy-on-write strikes".) Note viewI stays @[inline]: its result is always immediately matched, and branch selection forces it before any later state op.

3.2 progressLoop: the boxed forIn accumulator

The progress heartbeat's (--progress) for/mut loop compiled to forIn, whose state tuple (fe, s) stays live into the next step call — so the interned state entered every declaration at RC 2 and the first mutation struck (+110 G instructions in both modes). Fix: explicit tail recursion, accumulators as plain arguments (Main.lean:86).

3.3 diagLoop: the diagnostic second pass

"Non-progress is >20× slower" on Mathlib prefixes was not the verified fold — checkDeclsPure's List.foldlM compiles to a specialized tail-recursive loop threading state uniquely (confirmed in the generated C). It was checkMain's diagnostic second pass (error branch only, and every big Mathlib stream ends in a decline): its for d in decls2 loop's boxed state tuple kept the re-parsed arena at RC 2 into every step, so each declaration's first arena mutation copied the whole node/hash tables. Copy cost grows with the arena, which is why small streams never showed it. Fix: diagLoop, same explicit-recursion pattern (Main.lean:124; DESIGN.md "Mathlib-scoping driver fixes" item 2).

3.4 The FEnv cert branch (#99): closure capture across the value check

Every defnDecl cost a full copy of the FEnv.idx bucket array — a hidden O(n²) in the number of definitions. The driver branches kept fe live across checkDefnValP for the conditional Nat-op certification (certifyNatEqs (sharedOps fe) fe.env, checkDivModPinF … fe fe2, intentionally pre-insertion), so fe was pinned at RC 2 and the final fe.push copied the map. sharedOps fe (ConLeche/Kernel/CheckerS.lean:329) is a record of five closures each capturing fe — capture is an owned reference held for the callee's whole lifetime.

Fix (the use-then-consume shape): the rare branch is a pure name test over 16 pinned names, so it is decided before the value check; the common path tail-calls with fe consumed (CheckerS.lean:1252, :1504). Measured: copies 2532 → 297, init-prelude 27.98 G → 27.82 G, and the many scale shape's doubling exponent 1.16/1.27/1.43 → 1.00/1.00/1.01 (at n = 16000, 8.91 G → 4.54 G).

Show full SKILL.md (1,006 more words)Show less

4. Diagnosis toolkit

Work in this order; the striking frame lies (§4.5).

  1. dbgTraceIfShared probes at mutation sites — the diag/linearity pattern. Throwaway branch, probes at every persistent-container mutation: EStore.intern/internL (the node/cons table pushes) and FEnv.push's map-insert site, plus per-site tags so you can attribute counts to callers. Run the probe on your branch and on an identically-probed baseline and compare counts — absolute numbers mean nothing, deltas do. Revert the probes after. (DESIGN.md "Linearity of the reordered push"; the #99 and Mathlib-scoping audits used the same pattern.)
  2. Read the generated C. In .lake/build/ir/<Module>.c, find the mutation call and check for a surviving lean_inc_ref on the argument before it. The #64 confirmation read exactly this: in CheckerS.c's checkDefnValP the three (coreKnotI fe checkFuel) uses are CSE'd into one record, destructured and lean_dec_ref'd immediately; the last fe-capturing closure is consumed on the next line; FEnv_push(fe, …) receives fe with no surviving lean_inc_ref — the insert mutates in place. Also useful for confirming a foldlM really compiled to a unique-threading tail loop.
  3. Profile symbols. perf record / Samply: a tower of lean_copy_expand_array, lean_array_push, lean_del_core, lean_dec_ref_cold, lean_st_ref_set at the top is lost linearity, not work.
  4. Runtime gadget. Break on lean_copy_expand_array_nonlinear in gdb — the runtime's non-linearity hook — to catch the copies as they happen and count them per run.
  5. Attribute the holder, not the strike. RC 2 discovered at a mutation was taken far away: finish out of the copy, then set hardware watchpoints on the fresh tables' refcount words and scan the heap for holders. Freed-but-unreused shells (shallow lean_free_object of destructured records) make post-hoc pointer scans lie — only a watchpoint at the moment of the inc is conclusive.
  6. Measure with perf stat -e instructions:u, median of 3, with a per-shape startup baseline subtracted; wall-clock on a loaded machine is noise.

5. Two structural arguments that buy linearity for free

5.1 Snapshot / frozen-substrate

Read-only sharing is free: a frozen structure at RC 2 costs nothing because nobody mutates it. The two-tier arena is built on this — enableTierTwo freezes tier one and routes interns to tier two; truncateTierTwo drops tier two wholesale (Array.shrink 0, keeping capacity) and clears the flag. A "snapshot" is then a retained handle plus a pure header copy, and RC death of the snapshot is truncation — no transport theory needed. (DESIGN.md "Two-tier arena internals".)

5.2 The Bool barrier

If a per-item pipeline is split into an install phase (everything that produces or stores state) followed by a check phase whose result type is only success/failure, then at the moment the check phase ends no live reference into its temporaries can exist — a phase returning a Bool cannot retain. That makes dropping/truncating its allocations sound with no proof obligation, and it gives you the pre-push value for free: the check phase receives the very pre-push FEnv (the push happens after), so no counter-filtered view and no retained second map is needed. Measured to add zero copies over the pre-split baseline. (DESIGN.md "Driver split: install phase / Bool-barrier check phase".)

6. Codegen landmines (Nat arithmetic and initialization)

Evidence is lean.h at v4.33.0 — re-check on toolchain bumps; these are implementation facts, not guarantees.

OpCodegenVerdict
Nat.shiftLeft (<<<)LEAN_EXPORT lean_nat_shiftl — no inline scalar fast pathavoid on hot paths
Nat.shiftRight (>>>)static inline scalar fast pathfine
Nat.land (&&&), Nat.lor (|||), Nat.xorstatic inline scalar fast pathsfine
Nat.div, Nat.modstatic inline scalar fast pathsfine (div/mod-by-2 decode is cheap)
Nat.add, Nat.mulLEAN_ALWAYS_INLINE scalar fast pathssee mul caveat
  • <<< is the expensive one. In the #89 packed-keys experiment the shift form regressed every workload: init-prelude cert 26.6 G → 42.9 G instructions, recorded as +55–73 % at per-node frequency. Rewriting the lanes as mul/add Horner arithmetic fixed it (and is the omega-friendly form for injectivity proofs). Commit 878ecb3; refined in DESIGN.md "Tag scheme decision". Historical note: 878ecb3's message also called lean_nat_lor out-of-line; that is superseded — at v4.33.0 lean_nat_lor has a static inline scalar fast path and only lean_nat_shiftl is out-of-line.
  • Nat literals ≥ 2^32 compile to a runtime decimal parse. The emitter uses lean_unsigned_to_nat(n) up to 2^32 - 1 and lean_cstr_to_nat("…") above it — a GMP string parse at every evaluation of that literal expression. Measured at 5 % of the #89 probe (commit 4d60aca). Fix: hoist the literal behind a top-level def (parsed once), e.g. tierTag := 2^62 in ConLeche/Kernel/IExpr.lean. Separately, values above LEAN_MAX_SMALL_NAT = SIZE_MAX >> 1 = 2^63 - 1 leave the tagged-scalar regime entirely and become MPZ allocations — keep computed keys below 2^63.
  • Nat.mul's overflow check is a hardware division. lean_nat_mul's scalar path is r = n1*n2; if (r <= LEAN_MAX_SMALL_NAT && r / n1 == n2). Reading the source, prefer p + p to 2 * p in per-node arithmetic (not separately measured here — worth a quick perf stat if it is in your inner loop).
  • Dense keys need a mixer. Packed child indices cluster ~3× under the identity Hashable Nat even after Std's scramble (18.8 % of cycles in the intern bucket-chain walk). A def synonym of Nat with a Hashable that finalizes with one UInt64 multiply + xor-shift restores uniform buckets, stays scalar at runtime, and adds no proof obligations (4d60aca).
  • 0-ary closed defs run in the module initializer. They are evaluated at process start whenever the module's object code is linked in. A closed parse of a 1.96 MB embedded JSON cost ~0.26 G instructions at every process start (twice, under the OOM supervisor re-exec). Fix: make it a function of its input, so it runs only where it is applied — closed subterms extracted from function bodies become lazy once-cells, so no eager work remains (ConLeche/PinGen.lean:445-454).

7. Checklist before landing a hot-path change

  • No for/mut loop threads state on the hot path.
  • Rare/conditional branches decided before the expensive step they'd straddle.
  • No pure state read whose result is first used after an intervening call (else @[noinline] the reader).
  • No closure-capturing record built before a long call that ends in a mutation of the captured value.
  • Read-only traversal parameters borrowed (@&).
  • Per-node arithmetic free of <<< and of Nat literals ≥ 2^32.
  • Linearity verified by probe counts against an identically-probed baseline, or by absence of lean_inc_ref before the mutation in the generated C.
  • perf stat -e instructions:u, median of 3, startup-adjusted.

© leanprover, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/lean-rc-linearity of leanprover/con-leche.

Open the folder on GitHubat commit 67f0463

Compare with similar skills

Lean Rc Linearity next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Lean Rc Linearity compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Lean Rc Linearity this skillleanprover/con-leche122—~4.3kAutomated safety check: NotesApache-2.0
Nx Generatenomcopter/react-mosaic4.8k7 repos~1.9kAutomated safety check: PassCustom licence
PonytailDavidObando/gsharp5658 repos~1.7kAutomated safety check: PassMIT
Run Nx Generatornrwl/nx29k2 repos~592Automated safety check: NotesMIT
Conductor Setupgemini-cli-extensions/conductor3.8k—~4.2kAutomated safety check: PassApache-2.0
Mirage VFS Adapter Authoringstrukto-ai/mirage3.7k—~2.5kAutomated safety check: PassApache-2.0

Similar skills

  • Nx Generate

    nomcopter/react-mosaic

    Generate code using nx generators. An agent skill from nomcopter/react-mosaic.

    4.8k GitHub starsUsed in 7 repos~1.9k tokens
    DevelopmentAuto-check passed
  • Ponytail

    DavidObando/gsharp

    Forces the laziest solution that actually works, simplest, shortest, most minimal.

    565 GitHub starsUsed in 8 repos~1.7k tokens
    DevelopmentAuto-check passed
  • Run Nx generators with prioritization for workspace-plugin generators.

    29k GitHub starsUsed in 2 repos~592 tokens
    DevelopmentAuto-check: notes
  • Conductor Setup

    gemini-cli-extensions/conductor

    Scaffolds the project and sets up the Conductor environment.

    3.8k GitHub stars~4.2k tokensUpdated 1 mo ago
    DevelopmentAuto-check passed
  • Builds or extends a custom Mirage virtual filesystem adapter for an API, database, object store or app data, with a working mount configuration and filesystem tests.

    3.7k GitHub stars~2.5k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Enforces this repository's TypeScript backend module architecture under server/: feature folders, barrel exports, and where shared types and utilities belong.

    14k GitHub stars~1.2k tokensUpdated yesterday
    DevelopmentAuto-check passed

Categories

Questions about Lean Rc Linearity

What does Lean Rc Linearity do?

Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps. Lean Rc Linearity is an agent skill from leanprover/con-leche.

When should I use Lean Rc Linearity?

Lean Rc Linearity fits situations like: tasks that involve Project scaffolding.

How do I install Lean Rc Linearity in Claude Code?

Run `npx skills add leanprover/con-leche --skill lean-rc-linearity -a claude-code`. Or copy the skill folder (.claude/skills/lean-rc-linearity in leanprover/con-leche) into .claude/skills/lean-rc-linearity in your project. Claude Code loads it when a task matches its description.

How do I install Lean Rc Linearity in Codex?

Run `npx skills add leanprover/con-leche --skill lean-rc-linearity -a codex`. Or copy the skill folder (.claude/skills/lean-rc-linearity in leanprover/con-leche) into .agents/skills/lean-rc-linearity in your project. Codex loads it when a task matches its description.

Can I use Lean Rc Linearity in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add leanprover/con-leche --skill lean-rc-linearity -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/lean-rc-linearity, .gemini/skills/lean-rc-linearity, .github/skills/lean-rc-linearity and .opencode/skills/lean-rc-linearity in your project.

What does Lean Rc Linearity need to run?

SKILL.md names no scripts, command-line tools or credentials: Lean Rc Linearity is instructions for the agent only. Its frontmatter pre-approves these tools: Read, Bash, Grep.

Does Lean Rc Linearity access the network?

SKILL.md names 1 domain. As links in the text: lean-lang.org. This is read from the text; nothing was executed.

Is Lean Rc Linearity safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Lean Rc Linearity use?

Lean Rc Linearity is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Lean Rc Linearity use?

About 4.3k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Lean Rc Linearity?

Skills that share tags, products or a category with Lean Rc Linearity: Nx Generate (nomcopter/react-mosaic, 4.8k stars), Ponytail (DavidObando/gsharp, 565 stars), Run Nx Generator (nrwl/nx, 29k stars) and Conductor Setup (gemini-cli-extensions/conductor, 3.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Lean Rc Linearity?

leanprover (a GitHub organization) maintains it in leanprover/con-leche, which has 122 GitHub stars. The repository was last updated on October 5, 2026.

Source: leanprover/con-leche on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.