# From FHEVM Pain to a Production-Ready Skill: Engineering with LLMs at BootNode > Vibecoding gets you a prototype. Engineering practice, bottled as agent skills, gets you to production. Here is how we packaged our Zama FHEVM expertise into a Claude Code plugin and shipped it to the Zama Bounty Track. Date: 2026-05-13T00:00:00-03:00 Author: Maxi URL: https://blog.bootnode.dev/posts/from-fhevm-pain-to-production-ready-skill Beyond vibecoding, there's an engineering practice that puts LLMs to work without surrendering to them. At BootNode we keep sharpening that practice, to shorten time-to-release on real software, and to use fast prototypes as the way we discover, alongside our clients, the requirements, scope, and limitations of a problem. One way to push it forward: write **skills**. Structured packages of context (pinned versions, patterns, troubleshooting recipes, scripts, linters) that an agent loads on demand instead of being prompted from scratch every session. This post is about why we built one for Zama's FHEVM, what we packed into it, and the engineering loop around it that we think generalizes well beyond a single stack. ## Beyond vibecoding: the engineering layer Vibecoding (typing "build me an X" and accepting whatever comes back) gets you a weekend prototype, not production-ready software. The bottleneck isn't the model — it's the **context**: pinned versions, project conventions, the API your team agreed on last quarter, the pitfalls you only learn by shipping. Better prompts will not fix that. Better *context* will. A skill is a way to make that context portable, versioned, reviewable, and shareable across a team. It sits next to your linters and static analysis. They encode hard rules; the skill encodes the probabilistic, judgment-heavy knowledge that does not fit a single regex. ## Why we started with Zama FHEVM We had already taken Zama's stack for a spin earlier this year. The cryptography was excellent; the developer experience, [as we wrote at the time](https://blog.bootnode.dev/posts/zama-fhevm-developer-experience), was a different story: outdated examples, a missing cookbook for anything beyond an `FHECounter`, AI assistants confidently calling functions that no longer existed. By the time we came back to it, Zama had quietly shipped a new SDK ([`@zama-fhe/sdk@3.0.0`](https://github.com/zama-ai/sdk)) that deprecated `fhevmjs`, and `@fhevm/solidity@0.11.x` had renamed the entire `TFHE` namespace to `FHE`. The official docs were still catching up. That gap was exactly the kind of problem a skill is built for: a coherent version matrix and a usable API surface, captured once, reused every session. We also entered the work into [Zama's Developer Program Mainnet, Season 2](https://www.zama.org/post/zama-developer-program-mainnet-season-2-confidential-finance-is-the-next-frontier), themed around confidential finance. The point wasn't to win the prize but to get independent human evaluation of a piece of LLM tooling, a useful counterweight to the usual "ship it and hope" cycle. ## Anatomy of the skill The result is [`bn-fhevm`](https://github.com/BootNodeDev/zama-s2-bounty-skills), a Claude Code plugin that bundles ten namespaced skills (`bn-fhevm:fhevm-overview`, `bn-fhevm:fhevm-contracts`, and so on) alongside a canonical Hardhat workspace. What it captures: - **A pinned version matrix.** The FHEVM stack co-evolves: `@fhevm/solidity`, `@fhevm/hardhat-plugin`, `@openzeppelin/confidential-contracts`, and `@zama-fhe/sdk` only work together at specific pins. Get one wrong and the Hardhat plugin refuses to load. - **A breaking-rename catalogue.** Eight of them between v0.9 and v0.11. `TFHE → FHE` is the obvious one; `fhevmjs → @zama-fhe/sdk`, `ConfidentialFungibleToken → ERC7984`, `TFHESafeMath → FHESafeMath`, and a removed `FHE.requestDecryption` API trip you up just as often. Each entry pairs the wrong form with the correct one and a `grep` to verify a clean codebase. - **Twelve high-frequency footguns.** "Compile does not mean correct" is the recurring theme: missing `FHE.allowThis(handle)` after a state write compiles fine and reverts at runtime; view functions returning encrypted types compile fine and silently break the ACL contract. - **Patterns, not just APIs.** ACL lifecycle, ZKPoK input proofs, the v0.9+ three-step async decryption flow (`makePubliclyDecryptable` → off-chain `publicDecrypt` → on-chain `FHE.checkSignatures`). - **Tooling integration.** Slither, Aderyn, Semgrep, and Halmos against FHEVM contracts, including the `ZamaConfig` source-map workaround Slither needs. Frontend integration for React (Next.js App Router and Vite) via `` from `@zama-fhe/react-sdk`. - **Examples of increasing complexity.** Three flagship contracts (encrypted counter, ERC-7984 confidential token, confidential voting), more than the canonical `FHECounter`, each with mock-mode and Sepolia tests. - **References to the surrounding ecosystem.** OpenZeppelin's [ERC-7984 family](https://github.com/OpenZeppelin/openzeppelin-confidential-contracts) for confidential tokens, and Blockscout's recent [FHE-operation support in their explorer](https://www.blog.blockscout.com/fhe-operations-zama-block-explorer/). Neither existed the last time we shipped FHEVM code; both make a real difference. A `/create-template` wizard scaffolds the whole thing into a fresh repo in a single command: contracts-only, frontend-only, or both. ## The router pattern: keeping the context lean Stuffing every section above into one monolithic `SKILL.md` is the obvious mistake. The agent's context window is finite, signal-to-noise matters, and a 40 kB file flattens the relevance ranking. Instead, each of the ten skills is a separate file with a `description` frontmatter listing the triggers that should activate it ("FHEVM, confidential smart contracts, coprocessor, KMS, relayer, input proofs…"). Claude Code routes by matching the user's prompt against those descriptions, loads only what fits, and lets skills cross-reference each other explicitly (`See fhevm-setup`). The result is a small, relevant slice of context at every step, not the whole knowledge base flooded into a single prompt. ## How we built it The loop was deliberately boring: 1. Start from Anthropic's [`skill-creator`](https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md) skill for the structural skeleton: frontmatter, sectioning, naming. 2. Hand-write the content using our prior Zama experience as the seed. 3. Iterate with Trail of Bits' [`skill-improver`](https://github.com/trailofbits/skills/tree/main/plugins/skill-improver), which critiques skills for clarity, scope, and triggerability. 4. Validate against the canonical workspace: every code example in the skill compiles and runs against the same pinned stack. 5. Submit to the Zama bounty for external review. We ran the work itself the way we run client engagements: epics, issues, and pull requests, organized through our own SDLC skills (`/sdlc:issue`, `/sdlc:create-pr`, `/plan`, `/implement`, `/commit`, `/pre-review`). Same engineering hygiene, same review gates. The LLM was a contributor, not the project manager. ## Beyond a single skill: the surrounding practice A few habits we have settled into around skill development: - **Ephemeral [OrbStack](https://orbstack.dev/) Ubuntu VMs for clean-state experiments.** When measuring token usage, comparing prompt strategies, or stress-testing a skill's triggerability, we spin up a throwaway Ubuntu VM per run so memory, cached state, and previous-session bleed do not contaminate the result. - **Vendor neutrality by default.** Skills are plain markdown. We ship an `AGENTS.md` pointer that delegates to `CLAUDE.md` so the same content works in Cursor, Windsurf, Codex, Aider, or any other agent that reads agent files. Pinning the workflow to one IDE would defeat the point. - **Skills complement deterministic tools, not replace them.** Linters, type-checkers, fuzzers, and static analyzers stay where they are; the skill just teaches the agent how to invoke them in context. Slither still finds the bugs; the skill knows which Slither invocation actually works on an FHEVM codebase. ## See it in action A short walkthrough, from `/create-template` to a working confidential-payroll dApp on the latest pinned stack, end-to-end:
## What this is really about We can move faster with LLMs. That part is settled. The harder, more interesting problem is moving faster *while still building software that lasts*: software that survives the next refactor, the next team member, the next dependency bump. Skills are how we bridge that gap. They give the agent the augmented context it needs to do real engineering work, while keeping the human review loop, the static analysis, and the team conventions intact. Linters and types are not going anywhere — now joined by something a little more probabilistic and a lot more tailored: a shared, evolvable record of how *we* like to build with a given stack. If you are working with Zama's FHEVM, [`bn-fhevm`](https://github.com/BootNodeDev/zama-s2-bounty-skills) is installable today. If you are thinking about packaging your own team's expertise the same way and want to compare notes, reach out at [contact@bootnode.dev](mailto:contact@bootnode.dev) or [ping us on Telegram](https://t.me/mgarciap).