Scope: AI-agent-agnostic playbook for building applications with the Stoffel framework. This is not a maintainer guide for compiler, VM, protocol, or release engineering work. Dependency assumption: generated applications use current public crates.io releases by default. A pinned official GitHub revision is the fallback; a local path is explicit, nonportable framework-development mode only.
Use when
Use this playbook when building, running, testing, inspecting, or troubleshooting a Stoffel application through thestoffel command.
Current source of truth
crates/stoffel-cli/src/main.rscrates/stoffel-cli/src/project.rscrates/stoffel-cli/tests/cli.rscrates/stoffel-rust-sdk/src/input_file.rs
Core commands
stoffel run, build, and compile accept a project directory, source directory, single .stfl file, or existing .stflb depending on the command. build.source may point at either a file or a source directory; when it is a directory, the CLI recursively compiles all src/**/*.stfl files.
Project config shape
A typical app hasStoffel.toml:
[package].nameand[package].versionmust be non-empty.package.namemay use only letters, numbers,-, and_.build.sourcemust be a relative.stflfile path or a relative source directory inside the app.build.target_dirmust be a relative directory inside the app and cannot be undersrc/.optimization_levelmust be0..3.parties,threshold, andinstance_idmust be unquoted positive whole numbers.- HoneyBadger requires Byzantine topology: at least
4 * threshold + 1parties, with the current default of5parties and threshold1.
Backend and curve flags
Project config and CLI overrides support:--protocol aliases --backend; --curve aliases --field in CLI parsing. HoneyBadger does not take a curve suffix.
App templates
Usestoffel init --help for current template names. Current app-facing templates include:
Audit generated Rust apps
Immediately inspect every generatedCargo.toml; do not assume the CLI binary that generated it came from the same release as these docs. The portable default follows the versions on the current Rust SDK installation page:
path = "../stoffel/crates/stoffel-rust-sdk" is allowed only when a framework contributor explicitly selects nonportable local-checkout mode. It must not appear in a generated app intended for another user or repository.
Generated binary applications must include and commit Cargo.lock. After auditing Cargo.toml, regenerate the lockfile and use it for every check:
cargo-metadata.json, not only manifest text. Each Stoffel package’s source must be registry+... or the pinned official git+https://github.com/Stoffel-Labs/stoffel.git?...#<full-sha>. A null source identifies a path/workspace package and fails the portable-app check.
Prove portability from a clean external checkout with no sibling Stoffel repository:
Inputs
Named function inputs use repeated--input flags:
--client-input flags. Repeating the same slot appends values in order for that client:
--input a=1,b=2.
Input files
Both named inputs and ClientStore inputs can be loaded from.json, .csv, or .txt.
Named inputs:
0x-prefixed bytes depending on the execution path.
Bytecode and inspection
--program-info on run prints function/instruction metadata and client IO metadata before execution.
Validation / done criteria
For a CLI workflow change or app setup, collect real output from:# run-args: header when present.
Common pitfalls
stoffel run --configexpects network/off-chain config, not projectStoffel.toml.stoffel initcreates a project directory, not a single file.- Do not accept generated
path = "../stoffel/..."dependencies as a portable default. - Do not use
branch = "main", a tag, or an abbreviated Git SHA as the fallback; pin a full official revision. - Do not validate only from inside the Stoffel framework checkout, where workspace state can conceal dependency leaks.
- Do not rely on
cd app && ...in automation; pass explicit paths derived from the script or manifest. - If a path already contains
Stoffel.toml, usestoffel statusorstoffel run; do not re-init unless intentionally refreshing template files with--force. - Do not pass named inputs to ClientStore programs or ClientStore inputs to normal function-argument programs.
- Do not claim a command works unless it was actually run.