create-izi-noir 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +834 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -68,6 +68,16 @@ async function promptProjectOptions(defaults) {
68
68
  name: "initGit",
69
69
  message: "Initialize git repository?",
70
70
  initial: !defaults.skipGit
71
+ },
72
+ {
73
+ type: "select",
74
+ name: "aiTool",
75
+ message: "Which AI coding assistant do you use?",
76
+ choices: [
77
+ { title: "Claude Code", value: "claude", description: "Install IZI-NOIR circuit patterns skill" },
78
+ { title: "None / Other", value: "none", description: "Skip AI assistant configuration" }
79
+ ],
80
+ initial: 0
71
81
  }
72
82
  );
73
83
  try {
@@ -82,7 +92,8 @@ async function promptProjectOptions(defaults) {
82
92
  template: response.template || defaults.template || "default",
83
93
  provider: networkToProvider(network),
84
94
  skipInstall: response.installDeps === false,
85
- skipGit: response.initGit === false
95
+ skipGit: response.initGit === false,
96
+ aiTool: response.aiTool || "none"
86
97
  };
87
98
  } catch {
88
99
  return null;
@@ -1760,6 +1771,810 @@ export function EditableCodeBlock({
1760
1771
  `;
1761
1772
  }
1762
1773
 
1774
+ // src/generators/claude-skills.ts
1775
+ function generateClaudeSkills() {
1776
+ return {
1777
+ ".claude/skills/izi-noir-circuit-patterns/SKILL.md": SKILL_MD,
1778
+ ".claude/skills/izi-noir-circuit-patterns/assets/valid-examples.ts": VALID_EXAMPLES_TS,
1779
+ ".claude/skills/izi-noir-circuit-patterns/assets/operator-mapping.md": OPERATOR_MAPPING_MD
1780
+ };
1781
+ }
1782
+ var SKILL_MD = `---
1783
+ name: izi-noir-circuit-patterns
1784
+ description: >
1785
+ Patterns for writing JS/TS code that transpiles to Noir ZK circuits.
1786
+ Trigger: When writing circuit functions, IziNoir API, Solana deployment, Provider/Chain selection, or JS-to-Noir transformations.
1787
+ license: MIT
1788
+ metadata:
1789
+ author: izi-noir
1790
+ version: "2.0"
1791
+ scope: [sdk, frontend, solana-contracts]
1792
+ auto_invoke:
1793
+ - "circuit function"
1794
+ - "createProof"
1795
+ - "IziNoir"
1796
+ - "assert statement"
1797
+ - "JS to Noir"
1798
+ - "zero knowledge"
1799
+ - "Solana proof"
1800
+ - "Chain.Solana"
1801
+ - "Provider.Arkworks"
1802
+ allowed-tools: Read, Glob, Grep
1803
+ ---
1804
+
1805
+ # IZI-NOIR Circuit Patterns
1806
+
1807
+ Patterns for writing JavaScript/TypeScript code that the SDK can parse and transpile 1:1 to Noir ZK circuits, with Solana on-chain verification support.
1808
+
1809
+ ## When to Use
1810
+
1811
+ - Writing circuit functions for \`createProof()\`
1812
+ - Using the IziNoir class API (init, compile, prove, deploy, verifyOnChain)
1813
+ - Deploying proofs to Solana
1814
+ - Choosing between providers (Arkworks, Barretenberg)
1815
+ - Debugging parsing or Noir generation errors
1816
+ - Understanding JS \u2192 Noir type mapping
1817
+
1818
+ ## Architecture Overview
1819
+
1820
+ \`\`\`
1821
+ JS Function \u2192 AcornParser \u2192 NoirGenerator \u2192 Noir WASM \u2192 ArkworksWasm \u2192 Solana
1822
+ \`\`\`
1823
+
1824
+ **Pipeline layers:**
1825
+ 1. **Domain Layer** - Core types: Circuit, Proof, VerifyingKey, Provider, Chain, Network
1826
+ 2. **Application Layer** - Services: NoirGenerator, createProof orchestration
1827
+ 3. **Infrastructure Layer** - Parsers (Acorn), Compilers (Noir WASM), Provers (Arkworks/BB)
1828
+
1829
+ ## IziNoir Class API
1830
+
1831
+ ### Initialization
1832
+
1833
+ \`\`\`typescript
1834
+ import { IziNoir, Provider, Chain, Network } from '@izi-noir/sdk';
1835
+
1836
+ // Basic initialization (development)
1837
+ const izi = await IziNoir.init({
1838
+ provider: Provider.Arkworks,
1839
+ });
1840
+
1841
+ // With Solana chain targeting
1842
+ const izi = await IziNoir.init({
1843
+ provider: Provider.Arkworks,
1844
+ chain: Chain.Solana,
1845
+ network: Network.Devnet,
1846
+ });
1847
+ \`\`\`
1848
+
1849
+ ### Providers
1850
+
1851
+ | Provider | Use Case | Proof Size | Notes |
1852
+ |----------|----------|------------|-------|
1853
+ | \`Provider.Arkworks\` | **Solana production** | 256 bytes | Groth16, native syscalls |
1854
+ | \`Provider.Barretenberg\` | Development/testing | ~2KB | UltraPlonk, faster setup |
1855
+
1856
+ **Rule:** Always use \`Provider.Arkworks\` for Solana on-chain verification.
1857
+
1858
+ ### Chain and Network
1859
+
1860
+ \`\`\`typescript
1861
+ // Chain enum
1862
+ Chain.Solana // Format proofs for Solana verification
1863
+ Chain.EVM // Format proofs for EVM verification (future)
1864
+
1865
+ // Network enum
1866
+ Network.Devnet // Solana devnet
1867
+ Network.Mainnet // Solana mainnet
1868
+ Network.Localnet // Local validator
1869
+ \`\`\`
1870
+
1871
+ ### Creating Proofs
1872
+
1873
+ \`\`\`typescript
1874
+ // Define circuit function
1875
+ const balanceProof = (
1876
+ [threshold]: [number], // public inputs
1877
+ [balance]: [number] // private inputs
1878
+ ) => {
1879
+ assert(balance >= threshold);
1880
+ };
1881
+
1882
+ // Generate proof
1883
+ const result = await izi.createProof(
1884
+ balanceProof,
1885
+ [100], // public: threshold
1886
+ [1500] // private: actual balance
1887
+ );
1888
+
1889
+ console.log(result.verified); // true
1890
+ console.log(result.proof); // Uint8Array (256 bytes for Arkworks)
1891
+ \`\`\`
1892
+
1893
+ ### Solana Deployment
1894
+
1895
+ \`\`\`typescript
1896
+ // Deploy verifying key to Solana
1897
+ const deployment = await izi.deploy(balanceProof, {
1898
+ payer: wallet,
1899
+ network: Network.Devnet,
1900
+ });
1901
+
1902
+ console.log(deployment.vkAccount); // PublicKey of VK account
1903
+ console.log(deployment.programId); // Verifier program ID
1904
+
1905
+ // Verify proof on-chain
1906
+ const txSignature = await izi.verifyOnChain(result.proof, {
1907
+ vkAccount: deployment.vkAccount,
1908
+ payer: wallet,
1909
+ });
1910
+ \`\`\`
1911
+
1912
+ ### SolanaProofData Structure
1913
+
1914
+ When \`chain: Chain.Solana\`, proof data is formatted as:
1915
+
1916
+ \`\`\`typescript
1917
+ interface SolanaProofData {
1918
+ verifyingKey: {
1919
+ nr_pubinputs: number;
1920
+ vk_alpha_g1: number[]; // 64 bytes
1921
+ vk_beta_g2: number[]; // 128 bytes
1922
+ vk_gamma_g2: number[]; // 128 bytes
1923
+ vk_delta_g2: number[]; // 128 bytes
1924
+ vk_ic: number[][]; // (nr_pubinputs + 1) \xD7 64 bytes
1925
+ };
1926
+ proof: {
1927
+ ar: number[]; // 64 bytes - A point (G1)
1928
+ bs: number[]; // 128 bytes - B point (G2)
1929
+ krs: number[]; // 64 bytes - C point (G1)
1930
+ };
1931
+ publicInputs: number[][]; // Each input as 32-byte array
1932
+ }
1933
+ \`\`\`
1934
+
1935
+ ## Critical Patterns
1936
+
1937
+ ### 1. Function Signature (REQUIRED)
1938
+
1939
+ \`\`\`typescript
1940
+ // MUST use array destructuring for both parameters
1941
+ ([publicInputs], [privateInputs]) => {
1942
+ // body with assert statements
1943
+ }
1944
+
1945
+ // Example with multiple inputs
1946
+ ([expected, threshold], [secret, salt]) => {
1947
+ assert(secret * secret == expected);
1948
+ assert(secret > threshold);
1949
+ }
1950
+ \`\`\`
1951
+
1952
+ - First array: **public inputs** (marked \`pub\` in Noir)
1953
+ - Second array: **private inputs** (witness values)
1954
+ - Arrow function or function expression
1955
+ - Body: block statement \`{ }\` or single expression
1956
+
1957
+ ### 2. Mutability Convention
1958
+
1959
+ \`\`\`typescript
1960
+ // Immutable (default)
1961
+ let x = a + b; // \u2192 let x: Field = a + b;
1962
+
1963
+ // Mutable (use mut_ prefix)
1964
+ let mut_sum = 0; // \u2192 let mut sum: Field = 0;
1965
+ mut_sum = mut_sum + 1; // \u2192 sum = sum + 1;
1966
+ \`\`\`
1967
+
1968
+ **Rule:** Prefix variable name with \`mut_\` for mutable variables. The prefix is stripped in generated Noir.
1969
+
1970
+ ### 3. Operators
1971
+
1972
+ | JavaScript | Noir | Notes |
1973
+ |------------|------|-------|
1974
+ | \`==\` / \`===\` | \`==\` | Both map to equality |
1975
+ | \`!=\` / \`!==\` | \`!=\` | Both map to inequality |
1976
+ | \`+\` | \`+\` | Addition |
1977
+ | \`-\` | \`-\` | Subtraction |
1978
+ | \`*\` | \`*\` | Multiplication |
1979
+ | \`/\` | \`/\` | Division |
1980
+ | \`%\` | \`%\` | Modulo |
1981
+ | \`<\` | \`<\` | Less than |
1982
+ | \`>\` | \`>\` | Greater than |
1983
+ | \`<=\` | \`<=\` | Less than or equal |
1984
+ | \`>=\` | \`>=\` | Greater than or equal |
1985
+ | \`&&\` | \`&\` | **Converted to bitwise AND** |
1986
+ | \`\\|\\|\` | \`\\|\` | **Converted to bitwise OR** |
1987
+ | \`!\` | \`!\` | Logical NOT |
1988
+ | \`-x\` | \`-x\` | Negation |
1989
+
1990
+ **Warning:** \`&&\` and \`||\` are converted to bitwise operators in Noir!
1991
+
1992
+ ### 4. Statements
1993
+
1994
+ #### Assert
1995
+ \`\`\`typescript
1996
+ assert(condition); // Basic assertion
1997
+ assert(condition, "message"); // With error message
1998
+ \`\`\`
1999
+
2000
+ #### Variable Declaration
2001
+ \`\`\`typescript
2002
+ let x = a + b; // Immutable
2003
+ let mut_counter = 0; // Mutable (mut_ prefix)
2004
+ const y = 10; // Immutable (const supported)
2005
+ \`\`\`
2006
+
2007
+ #### Assignment (mutable only)
2008
+ \`\`\`typescript
2009
+ mut_x = mut_x + 1; // Only valid for mut_ variables
2010
+ \`\`\`
2011
+
2012
+ #### If/Else
2013
+ \`\`\`typescript
2014
+ if (condition) {
2015
+ // consequent
2016
+ } else {
2017
+ // alternate
2018
+ }
2019
+ \`\`\`
2020
+
2021
+ #### For Loop
2022
+ \`\`\`typescript
2023
+ // Exclusive range (i < end)
2024
+ for (let i = 0; i < 10; i++) { }
2025
+ // \u2192 for i in 0..10 { }
2026
+
2027
+ // Inclusive range (i <= end)
2028
+ for (let i = 1; i <= 5; i++) { }
2029
+ // \u2192 for i in 1..=5 { }
2030
+
2031
+ // Variable bounds
2032
+ for (let i = start; i < end; i++) { }
2033
+ // \u2192 for i in start..end { }
2034
+ \`\`\`
2035
+
2036
+ **Loop constraints:**
2037
+ - Init: \`let i = start\`
2038
+ - Test: \`i < end\` or \`i <= end\`
2039
+ - Update: \`i++\`, \`++i\`, or \`i = i + 1\`
2040
+
2041
+ ### 5. Expressions
2042
+
2043
+ #### Literals
2044
+ \`\`\`typescript
2045
+ 5 // number \u2192 Field
2046
+ 100n // bigint \u2192 Field
2047
+ "string" // string literal
2048
+ 0x1234 // hex value
2049
+ true / false // boolean \u2192 bool
2050
+ \`\`\`
2051
+
2052
+ #### Arrays
2053
+ \`\`\`typescript
2054
+ let arr = [a, b, c]; // \u2192 [Field; 3]
2055
+ arr[0] // static index
2056
+ arr[i] // dynamic index
2057
+ arr.length // \u2192 arr.len()
2058
+ \`\`\`
2059
+
2060
+ #### Ternary (conditional)
2061
+ \`\`\`typescript
2062
+ let result = cond ? a : b;
2063
+ // \u2192 let result: Field = if cond { a } else { b };
2064
+ \`\`\`
2065
+
2066
+ #### Method Calls
2067
+ \`\`\`typescript
2068
+ arr.len() // Array length
2069
+ \`\`\`
2070
+
2071
+ ### 6. Type Mapping
2072
+
2073
+ | JavaScript | Noir Type | Notes |
2074
+ |------------|-----------|-------|
2075
+ | \`number\` | \`Field\` | Default for all numerics |
2076
+ | \`bigint\` | \`Field\` | Converted to string |
2077
+ | \`boolean\` | \`bool\` | Only \`true\`/\`false\` literals |
2078
+ | \`[a,b,c]\` | \`[Field; 3]\` | Fixed-size array |
2079
+
2080
+ **Default type:** Everything is \`Field\` unless explicitly boolean.
2081
+
2082
+ ## NOT Supported
2083
+
2084
+ These JavaScript features **cannot** be parsed:
2085
+
2086
+ - Object literals \`{ key: value }\`
2087
+ - Destructuring (except function parameters)
2088
+ - Spread operator \`...\`
2089
+ - Rest parameters \`...args\`
2090
+ - Template literals \`\\\`\${x}\\\`\`
2091
+ - Async/await
2092
+ - While/do-while loops
2093
+ - Switch statements
2094
+ - Function declarations inside circuit
2095
+ - Closures over external variables
2096
+ - Class methods
2097
+ - Regular expressions
2098
+ - Try/catch
2099
+ - Break/continue
2100
+ - Return statements
2101
+ - Computed property assignment \`arr[i] = x\`
2102
+
2103
+ ## Code Examples
2104
+
2105
+ See [assets/valid-examples.ts](assets/valid-examples.ts) for complete working examples.
2106
+
2107
+ ## CLI: create-izi-noir
2108
+
2109
+ Scaffold new projects quickly:
2110
+
2111
+ \`\`\`bash
2112
+ # Interactive mode
2113
+ npx create-izi-noir
2114
+
2115
+ # Quick setup
2116
+ npx create-izi-noir my-project --yes
2117
+
2118
+ # With specific template
2119
+ npx create-izi-noir my-project --template balance-proof
2120
+
2121
+ # With specific provider
2122
+ npx create-izi-noir my-project --provider arkworks
2123
+ \`\`\`
2124
+
2125
+ **Templates:**
2126
+ - \`default\` - Balance proof + age verification circuits
2127
+ - \`minimal\` - Blank canvas with empty circuit
2128
+ - \`balance-proof\` - Just balance proof circuit
2129
+
2130
+ **Options:**
2131
+ - \`-t, --template <template>\` - Template to use
2132
+ - \`-p, --provider <provider>\` - Proving provider (arkworks/barretenberg)
2133
+ - \`-y, --yes\` - Skip prompts
2134
+ - \`--skip-install\` - Skip npm install
2135
+ - \`--skip-git\` - Skip git init
2136
+
2137
+ ## Frontend Integration (Vite)
2138
+
2139
+ \`\`\`typescript
2140
+ // vite.config.ts
2141
+ export default defineConfig({
2142
+ optimizeDeps: {
2143
+ exclude: ['@noir-lang/noirc_abi', '@noir-lang/acvm_js'],
2144
+ },
2145
+ });
2146
+
2147
+ // main.ts - Initialize WASM before use
2148
+ import initNoirC from '@noir-lang/noirc_abi';
2149
+ import initACVM from '@noir-lang/acvm_js';
2150
+ import acvm from '@noir-lang/acvm_js/web/acvm_js_bg.wasm?url';
2151
+ import noirc from '@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url';
2152
+ import { markWasmInitialized, IziNoir, Provider } from '@izi-noir/sdk';
2153
+
2154
+ await Promise.all([initACVM(fetch(acvm)), initNoirC(fetch(noirc))]);
2155
+ markWasmInitialized();
2156
+
2157
+ // Now IziNoir is ready
2158
+ const izi = await IziNoir.init({ provider: Provider.Arkworks });
2159
+ \`\`\`
2160
+
2161
+ ## Resources
2162
+
2163
+ - [Operator Mapping Table](assets/operator-mapping.md)
2164
+ - Parser: \`packages/sdk/src/infra/parser/AcornParser.ts\`
2165
+ - Generator: \`packages/sdk/src/application/services/NoirGenerator.ts\`
2166
+ - IziNoir Class: \`packages/sdk/src/IziNoir.ts\`
2167
+ `;
2168
+ var VALID_EXAMPLES_TS = `/**
2169
+ * Valid JS/TS Circuit Patterns for IZI-NOIR
2170
+ *
2171
+ * Each example shows the JS input and the generated Noir output.
2172
+ * All examples are valid and can be used with createProof().
2173
+ */
2174
+
2175
+ // Declare assert for TypeScript (SDK parses it, not executed)
2176
+ declare function assert(condition: boolean, message?: string): void;
2177
+
2178
+ // =============================================================================
2179
+ // Example 1: Basic Assertion (simplest circuit)
2180
+ // =============================================================================
2181
+ /**
2182
+ * JS Input:
2183
+ */
2184
+ export const basicAssertion = ([expected]: number[], [secret]: number[]) => {
2185
+ assert(secret * secret == expected);
2186
+ };
2187
+ /**
2188
+ * Generated Noir:
2189
+ * \`\`\`noir
2190
+ * fn main(secret: Field, expected: pub Field) {
2191
+ * assert(secret * secret == expected);
2192
+ * }
2193
+ * \`\`\`
2194
+ */
2195
+
2196
+ // =============================================================================
2197
+ // Example 2: Multiple Inputs with Arithmetic
2198
+ // =============================================================================
2199
+ /**
2200
+ * JS Input:
2201
+ */
2202
+ export const multipleInputs = (
2203
+ [sum, product]: number[],
2204
+ [a, b]: number[]
2205
+ ) => {
2206
+ assert(a + b == sum);
2207
+ assert(a * b == product);
2208
+ };
2209
+ /**
2210
+ * Generated Noir:
2211
+ * \`\`\`noir
2212
+ * fn main(a: Field, b: Field, sum: pub Field, product: pub Field) {
2213
+ * assert(a + b == sum);
2214
+ * assert(a * b == product);
2215
+ * }
2216
+ * \`\`\`
2217
+ */
2218
+
2219
+ // =============================================================================
2220
+ // Example 3: Variables and Mutability
2221
+ // =============================================================================
2222
+ /**
2223
+ * JS Input:
2224
+ */
2225
+ export const variablesAndMutability = (
2226
+ [expected]: number[],
2227
+ [a, b]: number[]
2228
+ ) => {
2229
+ // Immutable variable
2230
+ let sum = a + b;
2231
+
2232
+ // Mutable variable (mut_ prefix)
2233
+ let mut_result = 0;
2234
+ mut_result = sum * 2;
2235
+
2236
+ assert(mut_result == expected);
2237
+ };
2238
+ /**
2239
+ * Generated Noir:
2240
+ * \`\`\`noir
2241
+ * fn main(a: Field, b: Field, expected: pub Field) {
2242
+ * let sum: Field = a + b;
2243
+ * let mut result: Field = 0;
2244
+ * result = sum * 2;
2245
+ * assert(result == expected);
2246
+ * }
2247
+ * \`\`\`
2248
+ */
2249
+
2250
+ // =============================================================================
2251
+ // Example 4: Conditional Logic (if/else)
2252
+ // =============================================================================
2253
+ /**
2254
+ * JS Input:
2255
+ */
2256
+ export const conditionalLogic = (
2257
+ [threshold]: number[],
2258
+ [value]: number[]
2259
+ ) => {
2260
+ let mut_result = 0;
2261
+
2262
+ if (value > threshold) {
2263
+ mut_result = 1;
2264
+ } else {
2265
+ mut_result = 0;
2266
+ }
2267
+
2268
+ assert(mut_result == 1);
2269
+ };
2270
+ /**
2271
+ * Generated Noir:
2272
+ * \`\`\`noir
2273
+ * fn main(value: Field, threshold: pub Field) {
2274
+ * let mut result: Field = 0;
2275
+ * if value > threshold {
2276
+ * result = 1;
2277
+ * } else {
2278
+ * result = 0;
2279
+ * }
2280
+ * assert(result == 1);
2281
+ * }
2282
+ * \`\`\`
2283
+ */
2284
+
2285
+ // =============================================================================
2286
+ // Example 5: Ternary Expression
2287
+ // =============================================================================
2288
+ /**
2289
+ * JS Input:
2290
+ */
2291
+ export const ternaryExpression = (
2292
+ [threshold]: number[],
2293
+ [value]: number[]
2294
+ ) => {
2295
+ // Ternary converts to Noir if-expression
2296
+ let result = value > threshold ? 1 : 0;
2297
+ assert(result == 1);
2298
+ };
2299
+ /**
2300
+ * Generated Noir:
2301
+ * \`\`\`noir
2302
+ * fn main(value: Field, threshold: pub Field) {
2303
+ * let result: Field = if value > threshold { 1 } else { 0 };
2304
+ * assert(result == 1);
2305
+ * }
2306
+ * \`\`\`
2307
+ */
2308
+
2309
+ // =============================================================================
2310
+ // Example 6: For Loop with Array
2311
+ // =============================================================================
2312
+ /**
2313
+ * JS Input:
2314
+ */
2315
+ export const forLoopWithArray = (
2316
+ [expected]: number[],
2317
+ [a, b, c, d]: number[]
2318
+ ) => {
2319
+ let arr = [a, b, c, d];
2320
+ let mut_sum = 0;
2321
+
2322
+ // Exclusive range: i < 4 \u2192 for i in 0..4
2323
+ for (let i = 0; i < 4; i++) {
2324
+ mut_sum = mut_sum + arr[i];
2325
+ }
2326
+
2327
+ assert(mut_sum == expected);
2328
+ };
2329
+ /**
2330
+ * Generated Noir:
2331
+ * \`\`\`noir
2332
+ * fn main(a: Field, b: Field, c: Field, d: Field, expected: pub Field) {
2333
+ * let arr: [Field; 4] = [a, b, c, d];
2334
+ * let mut sum: Field = 0;
2335
+ * for i in 0..4 {
2336
+ * sum = sum + arr[i];
2337
+ * }
2338
+ * assert(sum == expected);
2339
+ * }
2340
+ * \`\`\`
2341
+ */
2342
+
2343
+ // =============================================================================
2344
+ // Example 7: Inclusive Range Loop
2345
+ // =============================================================================
2346
+ /**
2347
+ * JS Input:
2348
+ */
2349
+ export const inclusiveRangeLoop = ([expected]: number[], [n]: number[]) => {
2350
+ let mut_sum = 0;
2351
+
2352
+ // Inclusive range: i <= n \u2192 for i in 1..=n
2353
+ for (let i = 1; i <= n; i++) {
2354
+ mut_sum = mut_sum + i;
2355
+ }
2356
+
2357
+ assert(mut_sum == expected);
2358
+ };
2359
+ /**
2360
+ * Generated Noir:
2361
+ * \`\`\`noir
2362
+ * fn main(n: Field, expected: pub Field) {
2363
+ * let mut sum: Field = 0;
2364
+ * for i in 1..=n {
2365
+ * sum = sum + i;
2366
+ * }
2367
+ * assert(sum == expected);
2368
+ * }
2369
+ * \`\`\`
2370
+ */
2371
+
2372
+ // =============================================================================
2373
+ // Example 8: Nested Control Flow
2374
+ // =============================================================================
2375
+ /**
2376
+ * JS Input:
2377
+ */
2378
+ export const nestedControlFlow = ([max]: number[], []: number[]) => {
2379
+ let mut_evenSum = 0;
2380
+
2381
+ for (let i = 1; i <= max; i++) {
2382
+ // Nested if inside loop
2383
+ if (i % 2 == 0) {
2384
+ mut_evenSum = mut_evenSum + i;
2385
+ }
2386
+ }
2387
+
2388
+ assert(mut_evenSum > 0);
2389
+ };
2390
+ /**
2391
+ * Generated Noir:
2392
+ * \`\`\`noir
2393
+ * fn main(max: pub Field) {
2394
+ * let mut evenSum: Field = 0;
2395
+ * for i in 1..=max {
2396
+ * if i % 2 == 0 {
2397
+ * evenSum = evenSum + i;
2398
+ * }
2399
+ * }
2400
+ * assert(evenSum > 0);
2401
+ * }
2402
+ * \`\`\`
2403
+ */
2404
+
2405
+ // =============================================================================
2406
+ // Example 9: Comparison Operators
2407
+ // =============================================================================
2408
+ /**
2409
+ * JS Input:
2410
+ */
2411
+ export const comparisonOperators = (
2412
+ [min, max]: number[],
2413
+ [value]: number[]
2414
+ ) => {
2415
+ // All comparison operators
2416
+ assert(value >= min);
2417
+ assert(value <= max);
2418
+ assert(value != 0);
2419
+
2420
+ // Combined with arithmetic
2421
+ let doubled = value * 2;
2422
+ assert(doubled < max * 2);
2423
+ };
2424
+ /**
2425
+ * Generated Noir:
2426
+ * \`\`\`noir
2427
+ * fn main(value: Field, min: pub Field, max: pub Field) {
2428
+ * assert(value >= min);
2429
+ * assert(value <= max);
2430
+ * assert(value != 0);
2431
+ * let doubled: Field = value * 2;
2432
+ * assert(doubled < max * 2);
2433
+ * }
2434
+ * \`\`\`
2435
+ */
2436
+
2437
+ // =============================================================================
2438
+ // Example 10: Array Length Access
2439
+ // =============================================================================
2440
+ /**
2441
+ * JS Input:
2442
+ */
2443
+ export const arrayLengthAccess = (
2444
+ [expectedLen]: number[],
2445
+ [a, b, c]: number[]
2446
+ ) => {
2447
+ let arr = [a, b, c];
2448
+
2449
+ // .length converts to .len() in Noir
2450
+ assert(arr.length == expectedLen);
2451
+ };
2452
+ /**
2453
+ * Generated Noir:
2454
+ * \`\`\`noir
2455
+ * fn main(a: Field, b: Field, c: Field, expectedLen: pub Field) {
2456
+ * let arr: [Field; 3] = [a, b, c];
2457
+ * assert(arr.len() == expectedLen);
2458
+ * }
2459
+ * \`\`\`
2460
+ */
2461
+ `;
2462
+ var OPERATOR_MAPPING_MD = `# JavaScript to Noir Mapping Reference
2463
+
2464
+ Complete mapping of JavaScript constructs to their Noir equivalents.
2465
+
2466
+ ## Binary Operators
2467
+
2468
+ | JavaScript | Noir | Category | Example |
2469
+ |------------|------|----------|---------|
2470
+ | \`==\` | \`==\` | Equality | \`a == b\` \u2192 \`a == b\` |
2471
+ | \`===\` | \`==\` | Strict equality | \`a === b\` \u2192 \`a == b\` |
2472
+ | \`!=\` | \`!=\` | Inequality | \`a != b\` \u2192 \`a != b\` |
2473
+ | \`!==\` | \`!=\` | Strict inequality | \`a !== b\` \u2192 \`a != b\` |
2474
+ | \`+\` | \`+\` | Addition | \`a + b\` \u2192 \`a + b\` |
2475
+ | \`-\` | \`-\` | Subtraction | \`a - b\` \u2192 \`a - b\` |
2476
+ | \`*\` | \`*\` | Multiplication | \`a * b\` \u2192 \`a * b\` |
2477
+ | \`/\` | \`/\` | Division | \`a / b\` \u2192 \`a / b\` |
2478
+ | \`%\` | \`%\` | Modulo | \`a % b\` \u2192 \`a % b\` |
2479
+ | \`<\` | \`<\` | Less than | \`a < b\` \u2192 \`a < b\` |
2480
+ | \`>\` | \`>\` | Greater than | \`a > b\` \u2192 \`a > b\` |
2481
+ | \`<=\` | \`<=\` | Less or equal | \`a <= b\` \u2192 \`a <= b\` |
2482
+ | \`>=\` | \`>=\` | Greater or equal | \`a >= b\` \u2192 \`a >= b\` |
2483
+ | \`&&\` | \`&\` | Logical AND | \`a && b\` \u2192 \`a & b\` |
2484
+ | \`\\|\\|\` | \`\\|\` | Logical OR | \`a \\|\\| b\` \u2192 \`a \\| b\` |
2485
+
2486
+ > **Warning:** Logical operators \`&&\` and \`||\` are converted to bitwise operators \`&\` and \`|\` in Noir.
2487
+
2488
+ ## Unary Operators
2489
+
2490
+ | JavaScript | Noir | Category | Example |
2491
+ |------------|------|----------|---------|
2492
+ | \`!\` | \`!\` | Logical NOT | \`!a\` \u2192 \`!a\` |
2493
+ | \`-\` (prefix) | \`-\` | Negation | \`-a\` \u2192 \`-a\` |
2494
+
2495
+ ## Type Mapping
2496
+
2497
+ | JavaScript Type | Noir Type | Notes |
2498
+ |-----------------|-----------|-------|
2499
+ | \`number\` | \`Field\` | Default numeric type |
2500
+ | \`bigint\` | \`Field\` | Converted to string |
2501
+ | \`boolean\` | \`bool\` | Only \`true\`/\`false\` literals |
2502
+ | \`string\` | String literal | Quoted in Noir |
2503
+ | \`number[]\` | \`[Field; N]\` | Fixed-size array |
2504
+
2505
+ ## Statement Mapping
2506
+
2507
+ | JavaScript | Noir | Notes |
2508
+ |------------|------|-------|
2509
+ | \`assert(cond)\` | \`assert(cond)\` | Direct mapping |
2510
+ | \`assert(cond, "msg")\` | \`assert(cond, "msg")\` | With message |
2511
+ | \`let x = expr\` | \`let x: Type = expr\` | Immutable |
2512
+ | \`let mut_x = expr\` | \`let mut x: Type = expr\` | Mutable (prefix stripped) |
2513
+ | \`const x = expr\` | \`let x: Type = expr\` | Treated as let |
2514
+ | \`mut_x = expr\` | \`x = expr\` | Assignment (mutable only) |
2515
+ | \`if (c) { } else { }\` | \`if c { } else { }\` | No parens in Noir |
2516
+ | \`for (let i=s; i<e; i++)\` | \`for i in s..e { }\` | Exclusive range |
2517
+ | \`for (let i=s; i<=e; i++)\` | \`for i in s..=e { }\` | Inclusive range |
2518
+
2519
+ ## Expression Mapping
2520
+
2521
+ | JavaScript | Noir | Notes |
2522
+ |------------|------|-------|
2523
+ | \`x\` | \`x\` | Identifier |
2524
+ | \`5\` | \`5\` | Number literal |
2525
+ | \`100n\` | \`100\` | BigInt to Field |
2526
+ | \`"str"\` | \`"str"\` | String literal |
2527
+ | \`0x1234\` | \`0x1234\` | Hex preserved |
2528
+ | \`true\` / \`false\` | \`true\` / \`false\` | Boolean |
2529
+ | \`[a, b, c]\` | \`[a, b, c]\` | Array literal |
2530
+ | \`arr[i]\` | \`arr[i]\` | Index access |
2531
+ | \`arr.length\` | \`arr.len()\` | Length method |
2532
+ | \`c ? a : b\` | \`if c { a } else { b }\` | Ternary \u2192 if expr |
2533
+ | \`a + b * c\` | \`a + b * c\` | Precedence preserved |
2534
+
2535
+ ## Function Parameter Mapping
2536
+
2537
+ \`\`\`typescript
2538
+ // JavaScript
2539
+ ([pub1, pub2], [priv1, priv2]) => { ... }
2540
+
2541
+ // Noir (private params first, then public with 'pub')
2542
+ fn main(priv1: Field, priv2: Field, pub1: pub Field, pub2: pub Field) { ... }
2543
+ \`\`\`
2544
+
2545
+ ## Variable Naming Convention
2546
+
2547
+ | JavaScript | Noir | Rule |
2548
+ |------------|------|------|
2549
+ | \`x\` | \`x\` | Regular immutable |
2550
+ | \`mut_x\` | \`mut x\` | Mutable (prefix stripped) |
2551
+ | \`mut_counter\` | \`mut counter\` | Mutable (prefix stripped) |
2552
+
2553
+ ## For Loop Patterns
2554
+
2555
+ | JavaScript | Noir | Range Type |
2556
+ |------------|------|------------|
2557
+ | \`for (let i = 0; i < 10; i++)\` | \`for i in 0..10\` | Exclusive |
2558
+ | \`for (let i = 1; i <= 5; i++)\` | \`for i in 1..=5\` | Inclusive |
2559
+ | \`for (let i = start; i < end; i++)\` | \`for i in start..end\` | Variable bounds |
2560
+ | \`for (let i = 0; i < n; i = i + 1)\` | \`for i in 0..n\` | Alternative update |
2561
+
2562
+ ## Unsupported Operators
2563
+
2564
+ | JavaScript | Status | Alternative |
2565
+ |------------|--------|-------------|
2566
+ | \`**\` (exponent) | Not supported | Use multiplication loop |
2567
+ | \`<<\` (left shift) | Not supported | N/A |
2568
+ | \`>>\` (right shift) | Not supported | N/A |
2569
+ | \`>>>\` (unsigned shift) | Not supported | N/A |
2570
+ | \`&\` (bitwise AND) | Use \`&&\` | Converted to \`&\` |
2571
+ | \`\\|\` (bitwise OR) | Use \`\\|\\|\` | Converted to \`\\|\` |
2572
+ | \`^\` (XOR) | Not supported | N/A |
2573
+ | \`~\` (NOT) | Not supported | N/A |
2574
+ | \`in\` | Not supported | N/A |
2575
+ | \`instanceof\` | Not supported | N/A |
2576
+ `;
2577
+
1763
2578
  // src/commands/init.ts
1764
2579
  async function initCommand(projectName, options) {
1765
2580
  let projectOptions;
@@ -1769,7 +2584,8 @@ async function initCommand(projectName, options) {
1769
2584
  template: options.template,
1770
2585
  provider: options.provider,
1771
2586
  skipInstall: options.skipInstall,
1772
- skipGit: options.skipGit
2587
+ skipGit: options.skipGit,
2588
+ aiTool: "none"
1773
2589
  };
1774
2590
  } else {
1775
2591
  projectOptions = await promptProjectOptions({
@@ -1820,6 +2636,7 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
1820
2636
  }
1821
2637
  }
1822
2638
  if (!projectOptions.skipInstall) {
2639
+ console.log(pc3.dim(" Starting npm install..."));
1823
2640
  const installProgress = createInstallProgress();
1824
2641
  installProgress.start();
1825
2642
  try {
@@ -1830,6 +2647,7 @@ Error: Directory "${projectOptions.projectName}" already exists and is not empty
1830
2647
  console.log(pc3.yellow(' Run "npm install" manually.'));
1831
2648
  }
1832
2649
  }
2650
+ process.stdout.write("\x1B[?25h");
1833
2651
  printSuccessMessage(projectOptions);
1834
2652
  }
1835
2653
  async function createProjectStructure(projectDir, options, progress) {
@@ -1873,15 +2691,28 @@ async function createProjectStructure(projectDir, options, progress) {
1873
2691
  }
1874
2692
  files.push(["circuits/index.ts", generateCircuitsIndex(options.template)]);
1875
2693
  files.push(["circuits/types.d.ts", generateCircuitTypes()]);
2694
+ const hasSkills = options.aiTool === "claude";
1876
2695
  for (let i = 0; i < files.length; i++) {
1877
2696
  const [relativePath, content] = files[i];
1878
2697
  await writeFile(path2.join(projectDir, relativePath), content);
1879
- await progress.reportFile(relativePath, i === files.length - 1);
2698
+ await progress.reportFile(relativePath, !hasSkills && i === files.length - 1);
2699
+ }
2700
+ if (hasSkills) {
2701
+ const skillFiles = generateClaudeSkills();
2702
+ const skillEntries = Object.entries(skillFiles);
2703
+ for (let i = 0; i < skillEntries.length; i++) {
2704
+ const [relativePath, content] = skillEntries[i];
2705
+ await writeFile(path2.join(projectDir, relativePath), content);
2706
+ await progress.reportFile(relativePath, i === skillEntries.length - 1);
2707
+ }
1880
2708
  }
1881
2709
  }
1882
2710
  function printSuccessMessage(options) {
1883
2711
  console.log();
1884
2712
  console.log(pc3.green("\u2713") + " Project created successfully!");
2713
+ if (options.aiTool === "claude") {
2714
+ console.log(pc3.green("\u2713") + " Claude Code skill installed " + pc3.dim("(.claude/skills/izi-noir-circuit-patterns)"));
2715
+ }
1885
2716
  console.log();
1886
2717
  console.log("Next steps:");
1887
2718
  console.log();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-izi-noir",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "CLI to scaffold IZI-NOIR ZK projects",
5
5
  "type": "module",
6
6
  "bin": {