This guide gets you from a fresh install to a working Stoffel project. You will create a project, inspect its structure, build Stoffel bytecode, and run the program through local MPC on your machine.
Copy-paste path
Use this block when you want the fastest verified default app, or when you are asking an AI coding agent to do the setup for you:
Success means the CLI creates the project, stoffel check validates src/main.stfl, stoffel build writes .stflb bytecode under target/, the local MPC run completes, and the Rust wrapper builds and runs. If any command fails, keep its exact output and use the troubleshooting section before changing the app.
Create a Stoffel project
After installing the stoffel CLI, create and enter a new project:
The default template creates a Rust-backed Stoffel project:
There are four important files to start with:
src/main.stfl: the StoffelLang program that compiles to .stflb bytecode.
Stoffel.toml: package, build, and MPC topology settings such as parties and threshold.
src/main.rs: a Rust SDK wrapper that calls the same Stoffel program from Rust application code.
src/stoffel_bindings.rs: generated program metadata used by the Rust wrapper.
Check and build
Validate the Stoffel source and project configuration:
Expected output includes the checked source path and the functions found in the program:
Build bytecode under target/:
Expected output includes the generated .stflb file:
Inspect the generated bytecode before running local MPC:
This prints the functions, inferred register classes, and instructions in the compiled program. If your project name produces a different bytecode file name, use the .stflb file that stoffel build wrote under target/debug/.
Run local MPC during development
Run the generated example through local MPC:
Local MPC testing runs the compiled program by spawning several MPC nodes/processes locally on your machine. The default project uses five parties with threshold one unless you override those settings.
For one-shot development runs, use stoffel dev --once:
For watch mode, remove --once:
stoffel dev watches Stoffel.toml and your source tree, rebuilds after changes, and reruns through local MPC.
Template programs can differ. Use the generated README.md and src/main.stfl to confirm whether the program expects named function inputs with --input or client share inputs with --client-input.
Run the Rust SDK wrapper
The default template also includes src/main.rs, a Rust application wrapper around the Stoffel program. It lets you call the same src/main.stfl program from Rust code instead of only from the CLI.
The generated wrapper currently:
- imports
stoffel::prelude::*;
- loads
src/stoffel_bindings.rs with mod stoffel_bindings;;
- creates an async
tokio main function;
- references
stoffel_bindings::ProgramManifest, the generated manifest for the compiled program shape;
- compiles
src/main.stfl with Stoffel::compile_file("src/main.stfl")?;
- applies the local MPC topology with
.parties(5) and .threshold(1);
- runs the program with
.execute_local().await?, which is for local testing where several MPC nodes are spawned locally on your machine;
- prints the first returned value.
Build and run the wrapper with Cargo:
If you change the program’s ClientStore input or output shape, regenerate or update the generated bindings before relying on the Rust wrapper.
Edit the program
Open src/main.stfl and make a small change. Then rerun the fast check/build loop:
When the program uses client-provided shares, pass local client inputs by slot:
Use named inputs for programs that define ordinary function arguments:
What the quick start covers
The core Stoffel development loop is:
- Write the MPC program in
src/main.stfl.
- Run
stoffel check for fast validation.
- Run
stoffel build to produce .stflb bytecode.
- Run
stoffel run or stoffel dev for local MPC development.
- Use the Rust SDK wrapper when integrating the program into an application.
In local MPC execution:
- private values are modeled as shares;
- the program computes over shares instead of exposing raw inputs;
- outputs are reconstructed only where the program opens or sends them;
- several MPC nodes/processes run locally on your machine;
- party and threshold settings come from
Stoffel.toml, SDK builder calls, or command-line flags.
Recommended workflow
Use the fastest command that answers your current question:
| Goal | Command |
|---|
| Validate source and settings | stoffel check |
| Build bytecode | stoffel build |
| Inspect compiled bytecode | stoffel compile --disassemble target/debug/hello-mpc.stflb |
| Run once through local MPC | stoffel dev --once |
| Iterate on an MPC program | stoffel dev |
| Build the Rust app wrapper | cargo build |
| Run the Rust app wrapper | cargo run |
Use with AI coding agents
If you want an AI coding agent to help build a Stoffel app, give it the Stoffel skills and live docs access before asking it to write code. See Installation for the copy-paste setup prompt, skills setup, and docs MCP setup.
Choose the skill based on the task:
| User task | Start with |
|---|
| Create the first app and prove the toolchain works | Stoffel App Getting Started |
| Build a custom private-computation app | Stoffel Full App Golden Path |
Write or modify .stfl source | Stoffel-Lang App Programming |
Use ClientStore, secret shares, or client outputs | Stoffel Secret MPC Programming |
| Integrate with Rust application code | Stoffel Rust App SDK |
| Run local MPC loops or debug local execution | Stoffel Local MPC Dev Loop |
| Prepare network or deployment handoff | Stoffel Deployment Runbook |
When reviewing agent work, ask for the exact command output from stoffel check, stoffel build, a local MPC run, and any Rust build/test command the agent changed. Do not accept a code-only answer for a runnable app task.
Troubleshooting
Check the generated README.md and src/main.stfl:
- Use
--input NAME=VALUE for ordinary named function inputs.
- Use
--client-input SLOT=VALUE for programs that call ClientStore.take_share.
I want the exact flags for my CLI version
Use command-specific help:
Next steps