o1js-skillsCAUTION
Agent skill for writing correct, secure o1js 3 zkApps on Mina after the Mesa hard fork, backed by tests that run on o1js 3.1.0.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Install · What it covers · Does it help? · Backed by tests · Contributing
An agent skill that teaches AI coding assistants (Claude Code, Codex, Cursor and others that read SKILL.md) to write correct, secure o1js 3 code for Mina zkApps after the Mesa hard fork.
[!IMPORTANT] In our evaluation, Claude Sonnet without the skill wrote a token that compiled and passed its own tests, and a stranger then minted 1,000,000 of it. With the skill, the same attack was rejected. Details
Install
Any agent that supports Agent Skills, via the skills CLI:
npx skills add izzetemredemir/o1js-skills
Claude Code plugin, or manual install
Claude Code plugin:
/plugin marketplace add izzetemredemir/o1js-skills /plugin install o1js-skills
Manual (Claude Code, personal skill):
git clone https://github.com/izzetemredemir/o1js-skills mkdir -p ~/.claude/skills ln -s "$PWD/o1js-skills/skills/o1js" ~/.claude/skills/o1js
For a single project, link it into tha
a64a358bc92bOBSERVED · 2026-10-10Install
Commands as the repository documents them. They are shown, not run.
npx skills add izzetemredemir/o1js-skills
git clone https://github.com/izzetemredemir/o1js-skills
npm install
npm init -y
npm install o1js@^3.1.0
npm install -D typescript @types/node
Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| codex | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: o1js
description: Write, review, debug and upgrade Mina zkApps and zero-knowledge programs with o1js 3.x. Use when the user works with o1js or Mina smart contracts (SmartContract, @state, @method), ZkProgram and recursive proofs, actions and reducers, custom tokens (TokenContract), permissions and verification-key upgrades, Mina transactions and fees, browser zkApp frontends and wallet (Auro) integration, LocalBlockchain or lightnet tests, deploying to Mina devnet or mainnet, the Mesa hard fork, or errors such as "Account_app_state_precondition_unsatisfied", "Update_not_permitted_access", "too many segments" or "Invalid_fee_excess". Corrects the o1js 0.x–2.x APIs that models tend to produce.
license: MIT
compatibility: o1js 3.1.x on Mina after the Mesa hard fork; Node.js >= 22.19.5
metadata:
version: "0.1.0"
o1js: "3.1.0"
---
# o1js 3 on Mesa
Your memory of o1js is probably out of date. o1js 3.0 (published 2026-08-18) and 3.1 (published 2026-09-23) shipped alongside the Mesa hard fork (Mina mainnet, 2026-09-03), and most public o1js code was written for 0.x–2.x. Everything here was checked against o1js 3.1.0. Claims that cite an example are reproduced by the tests in [examples/](examples/).
## Before writing code
1. **Check the installed version** (`node_modules/o1js/package.json`). On 3.x, follow this skill. On 2.x or older, read [references/migration.md](references/migration.md) first. Since Mesa, mainnet contracts need o1js 3.
2. **Don't guess signatures.** Read the installed typings: `node_modules/o1js/dist/node/index.d.ts` and `dist/node/lib/**/*.d.ts`. The CHANGELOG in the o1js repo lists every change by version.
3. **Treat docs and tutorials as possibly stale.** Several official pages still show pre-v3 or buggy code ([references/mesa.md](references/mesa.md#known-documentation-bugs)).
## Default stack
- **Versions:** `o1js@^3.1.0` and Node.js ≥ 22.19.5. 3.1.0 fixes account-update soundness bugs in 3.0.x and changes verification keys again.
- **Build with `tsc`.** The tsconfig needs `experimentalDecorators: true`, `emitDecoratorMetadata: true` and `useDefineForClassFields: false`. o1js reads decorator metadata to learn `@method` argument types, and esbuild-based runners (tsx, Vite, Vitest) do not emit it. Template: [examples/tsconfig.json](examples/tsconfig.json).
- **Testing:** `node:test` with `await Mina.LocalBlockchain({ proofsEnabled: false })` for fast logic tests. Run the same suite with proofs enabled before any deployment. See [references/testing.md](references/testing.md).
- **Proving:**
- Node: `setBackend('native')` at the top of the entry point, before any o1js call that initialises it (`LocalBlockchain`, `compile`, ...), or `O1JS_BACKEND=native`, for about 2× faster proving.
- Browser: WASM inside a Web Worker, served with COOP/COEP headers.
- Cache keys with `Cache.FileSystem`.
- **zkapp-cli:** `zk project` still scaffolds `"o1js": "^2.*"`. Change it to `^3.1.0` before writing any code.
## What models get wrong most often
| Outdated pattern | o1js 3.1 | Proof |
|---|---|---|
| `Mina.Network(url)` for mainnet | `Mina.Network({ networkId: 'mainnet', mina: url, archive })`; the bare URL defaults to **devnet**, so signatures are invalid on mainnet | [api-surface.test.ts](examples/api-surface/api-surface.test.ts) |
| `Mina.LocalBlockchain()` without await, `testAccounts[0].privateKey` | `const local = await Mina.LocalBlockchain(...)`, `const [alice] = local.testAccounts; alice.key` | same |
| `@method inc() {}` | `@method async inc() {}` and `await zkApp.inc()` | [type-checks.ts](examples/api-surface/type-checks.ts) |
| `Mina.transaction(sender, () => {...})` | `Mina.transaction(sender, async () => {...})` | same |
| `const proof = await Program.m(x)`, method returns `x` | `const { proof } = await Program.m(x)`, method returns `{ publicOutput: x }`; `await Program.verify(proof)` | same, [SumProgram.test.ts](examples/zkprogram/SumProgram.test.ts) |
| `this.x.get()` alone | `this.x.getAndRequireEquals()`; a contract with a bare `get()` does not compile | [Pitfalls.test.ts](examples/pitfalls/Pitfalls.test.ts) |
| `setVerificationKey: Permissions.impossible()` | `setVerificationKey: Permissions.VerificationKey.impossibleDuringCurrentVersion()` (or `.proofDuringCurrentVersion()`, `.signature()`) | [type-checks.ts](examples/api-surface/type-checks.ts) |
| Calling `deploy()` again to upgrade | Signed verification-key update; `deploy()` resets every permission to the defaults | [Upgradable.test.ts](examples/upgrade/Upgradable.test.ts) |
| `AccountUpdate.createIf(c, pk)` used as an `AccountUpdate` | Returns `OptionalAccountUpdate`; use `.value` | [type-checks.ts](examples/api-surface/type-checks.ts) |
| `UInt64.lt`, `Field.isZero`, `Circuit.if`, `CircuitValue`, `isReady` | `lessThan`, `x.equals(0)`, `Provable.if`, `Struct`; `isReady` is gone | [api-surface.test.ts](examples/api-surface/api-surface.test.ts) |
| `encryptV2`, `TokenContractV2`, `divV2`, ... | Plain names (`encrypt`, `TokenContract`, `div`) since 2.0 | same |
| `import { fetchActions } from 'o1js'` | `Mina.fetchActions(...)`; `fetchEvents` is still top-level | same |
| `Provable.equal(a, b)` | `Provable.equal(Type, a, b)` | same |
| `uint32.toBigInt()` | `UInt64`/`UInt8`: `toBigInt()`; `UInt32`/`Int64`: `toBigint()` | same |
| `amount.assertEquals(x, 'message')` on `UInt64`/`UInt32` | No message argument there (compile error); use `amount.equals(x).assertTrue('message')`. Comparisons such as `assertLessThanOrEqual` do take one | [type-checks.ts](examples/api-surface/type-checks.ts) |
| `setFeePerSnarkCost`, `TransactionCost.*` | `tx.setFee(...)`; limit is 16 segments per transaction | [Limits.test.ts](examples/limits/Limits.test.ts) |
| 8 state fields | 32 field elements of on-chain state per account | same |
| `Experimental.IndexedMerkleMap` | Top-level `IndexedMerkleMap`; `OffchainState` is still under `Experimental` | [api-surface.test.ts](examples/api-surface/api-surface.test.ts) |
The Trust audit
CAUTIONgrade B · trust 89/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | FAIL |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (7)
- Read keys from environment variables or files the user controls.
exploit.test.ts
assert.equal(Mina.Network('http://127.0.0.1:1/graphql').getNetworkId(), 'devnet');const mainnet = Mina.Network({ networkId: 'mainnet', mina: 'http://127.0.0.1:1/graphql' });- It provides GraphQL at `http://127.0.0.1:8080/graphql`, the archive at `http://127.0.0.1:8282` and the account manager at `http://127.0.0.1:8181`.
mina: 'http://127.0.0.1:8080/graphql',
archive: 'http://127.0.0.1:8282',
Gates applied: no_behavioural_pass.
a64a358bc92bfull audit observations/trust-audit/skill/izzetemredemir__o1js-skills.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-10 | a64a358bc92b | CAUTION | B | 89 | first audit |
Questions
What does the o1js-skills skill do?
Agent skill for writing correct, secure o1js 3 zkApps on Mina after the Mesa hard fork, backed by tests that run on o1js 3.1.0.
Is o1js-skills safe to install?
With care. The audit graded it B (89/100) and found 7 things worth knowing before you trust this skill, listed below with the exact line each was found on.
What can o1js-skills access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does o1js-skills work with?
Its documentation mentions claude-code, codex and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (a64a358bc92b), read on 2026-10-10. The repository is watched, and a new audit runs when it changes — this is the first audit.