Nx Generate
nomcopter/react-mosaic
Generate code using nx generators. An agent skill from nomcopter/react-mosaic.
Lean 4 reference-counting and linearity: how to keep hot data structures unshared, diagnose copies, and avoid codegen traps
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install leanprover/con-leche lean-rc-linearity --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .claude/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearityType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install leanprover/con-leche lean-rc-linearity --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .agents/skills/lean-rc-linearity && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .agents/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install leanprover/con-leche lean-rc-linearity --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .cursor/skills/lean-rc-linearity && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .cursor/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/leanprover/con-leche.git --path .claude/skills/lean-rc-linearity--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install leanprover/con-leche lean-rc-linearity --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .gemini/skills/lean-rc-linearity && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .gemini/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install leanprover/con-leche lean-rc-linearityInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .github/skills/lean-rc-linearity && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .github/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add leanprover/con-leche --skill lean-rc-linearity -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install leanprover/con-leche lean-rc-linearity --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/leanprover/con-leche.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/lean-rc-linearity .opencode/skills/lean-rc-linearity && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "lean-rc-linearity" agent skill from https://github.com/leanprover/con-leche/tree/master/.claude/skills/lean-rc-linearity into .opencode/skills/lean-rc-linearity/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "lean-rc-linearity", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
lean-rc-linearityLean 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. 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.
8 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 67f0463. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadBashGrepFrom allowed-tools in the SKILL.md frontmatter.
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.
Links to these hosts (documentation or services it may open):
lean-lang.orgFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Bash, GrepAutomated 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.
The full file from leanprover/con-leche at commit 67f0463, republished under its Apache-2.0 licence (© leanprover). 2,336 words, ~4,331 tokens.
.claude/skills/lean-rc-linearity/SKILL.md (or your agent's skills folder).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.
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).
DESIGN.md "FEnv
linearity", §3.4.)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.)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).HashMap.alter over
getD + insert; Array.modify/set over read-then-write.@[noinline] (§3.1).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).@& (or inferred borrowing) elides RC on
traversals entirely (§2.3).Bool. It provably cannot retain anything
it built (§5.2).Every heap object starts with an 8-byte header:
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'.
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.
Three argument kinds:
uint8, tagged) — never RC-ed;(x : obj) — the callee must dec it;(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).
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.@[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.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.)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.
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.
@[noinline] withStorewithStore 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.
progressLoop: the boxed forIn accumulatorThe 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).
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).
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).
Work in this order; the striking frame lies (§4.5).
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.).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.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.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.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.perf stat -e instructions:u, median of 3, with a per-shape
startup baseline subtracted; wall-clock on a loaded machine is noise.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".)
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".)
Evidence is lean.h at v4.33.0 — re-check on toolchain bumps; these are
implementation facts, not guarantees.
| Op | Codegen | Verdict |
|---|---|---|
Nat.shiftLeft (<<<) | LEAN_EXPORT lean_nat_shiftl — no inline scalar fast path | avoid on hot paths |
Nat.shiftRight (>>>) | static inline scalar fast path | fine |
Nat.land (&&&), Nat.lor (|||), Nat.xor | static inline scalar fast paths | fine |
Nat.div, Nat.mod | static inline scalar fast paths | fine (div/mod-by-2 decode is cheap) |
Nat.add, Nat.mul | LEAN_ALWAYS_INLINE scalar fast paths | see 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).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).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).for/mut loop threads state on the hot path.@[noinline] the reader).@&).<<< and of Nat literals ≥ 2^32.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
Just SKILL.md in .claude/skills/lean-rc-linearity of leanprover/con-leche.
Open the folder on GitHubat commit 67f0463
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Lean Rc Linearity this skillleanprover/con-leche | 122 | — | ~4.3k | Automated safety check: Notes | Apache-2.0 | |
| Nx Generatenomcopter/react-mosaic | 4.8k | 7 repos | ~1.9k | Automated safety check: Pass | Custom licence | |
| PonytailDavidObando/gsharp | 565 | 8 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Run Nx Generatornrwl/nx | 29k | 2 repos | ~592 | Automated safety check: Notes | MIT | |
| Conductor Setupgemini-cli-extensions/conductor | 3.8k | — | ~4.2k | Automated safety check: Pass | Apache-2.0 | |
| Mirage VFS Adapter Authoringstrukto-ai/mirage | 3.7k | — | ~2.5k | Automated safety check: Pass | Apache-2.0 |
nomcopter/react-mosaic
Generate code using nx generators. An agent skill from nomcopter/react-mosaic.
DavidObando/gsharp
Forces the laziest solution that actually works, simplest, shortest, most minimal.
nrwl/nx
Run Nx generators with prioritization for workspace-plugin generators.
gemini-cli-extensions/conductor
Scaffolds the project and sets up the Conductor environment.
strukto-ai/mirage
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.
siteboon/claudecodeui
Enforces this repository's TypeScript backend module architecture under server/: feature folders, barrel exports, and where shared types and utilities belong.
Categories
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.
Lean Rc Linearity fits situations like: tasks that involve Project scaffolding.
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.
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.
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.
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.
SKILL.md names 1 domain. As links in the text: lean-lang.org. This is read from the text; nothing was executed.
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.
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.
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.
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.
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.