Help us improve
Share bugs, ideas, or general feedback.
From noir
Workflow for measuring and optimizing the ACIR circuit size of a constrained Noir program. Use when asked to optimize a Noir program's gate count or circuit size.
npx claudepluginhub critesjosh/noir-claude-plugin --plugin noirHow this skill is triggered — by the user, by Claude, or both
Slash command
/noir:noir-optimize-acirThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This workflow targets **ACIR circuit size** for constrained Noir programs. It does not apply to `unconstrained` (Brillig) functions — Brillig runs on a conventional VM where standard profiling and algorithmic improvements apply instead, and `bb gates` won't reflect Brillig performance.
This skill should be used when the user asks about Compact circuit costs, ZK proof generation costs, gate counts, loop unrolling behavior, hash function cost tradeoffs (transientHash vs persistentHash), commitment function costs (transientCommit vs persistentCommit), pure circuit optimization benefits, vector operation costs (map/fold/slice unrolling), compiler optimization passes, runtime gas model (readTime, computeTime, bytesWritten, bytesDeleted), ledger state storage costs, privacy-cost tradeoffs, or how to write cost-efficient Compact smart contracts on Midnight.
Profiles Cairo code, identifies bottlenecks, and applies targeted optimizations for gas/steps reduction, arithmetic, BoundedInt, and storage packing after correctness is established.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Share bugs, ideas, or general feedback.
This workflow targets ACIR circuit size for constrained Noir programs. It does not apply to unconstrained (Brillig) functions — Brillig runs on a conventional VM where standard profiling and algorithmic improvements apply instead, and bb gates won't reflect Brillig performance.
Compile the program and measure gate count with:
nargo compile && bb gates -b ./target/<package>.json
Libraries cannot be compiled with nargo compile. Instead, mark the functions you want to measure with #[export] and use nargo export:
nargo export && bb gates -b ./export/<function_name>.json
Artifacts are written to the export/ directory and named after the exported function (not the package).
If bb is not available, ask the user for their backend's equivalent command. Other backends should have a similar CLI interface.
The output contains two fields:
circuit_size: the actual gate count after backend compilation. This determines proving time, which is generally the bottleneck.acir_opcodes: number of ACIR operations. This affects execution time (witness generation). A change can reduce opcodes without affecting circuit size or vice versa — both matter, but prioritize circuit_size when they conflict.Always record a baseline of both metrics before making changes.
circuit_size.circuit_size to the baseline.circuit_size increased or stayed the same, undo the change. Not every "optimization" helps — the compiler may already handle it, or the overhead of the new approach may outweigh the savings.Candidate optimizations roughly ordered by impact:
if c { assert_eq(x, a) } else { assert_eq(x, b) } with assert_eq(x, if c { a } else { b }).<, <=) cost more than equality (==). But don't introduce extra state to avoid them — measure first.if/else expressions compile to the same circuit as c * (a - b) + b.<= with flag tracking without measuring: adding mutable state across loop iterations can produce more gates than a simple comparison.