Skip to main content
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 the stoffel command.

Current source of truth

  • crates/stoffel-cli/src/main.rs
  • crates/stoffel-cli/src/project.rs
  • crates/stoffel-cli/tests/cli.rs
  • crates/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 has Stoffel.toml:
Rules enforced by the CLI:
  • [package].name and [package].version must be non-empty.
  • package.name may use only letters, numbers, -, and _.
  • build.source must be a relative .stfl file path or a relative source directory inside the app.
  • build.target_dir must be a relative directory inside the app and cannot be under src/.
  • optimization_level must be 0..3.
  • parties, threshold, and instance_id must be unquoted positive whole numbers.
  • HoneyBadger requires Byzantine topology: at least 4 * threshold + 1 parties, with the current default of 5 parties and threshold 1.

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

Use stoffel init --help for current template names. Current app-facing templates include:
Treat non-Rust wrapper templates as integration scaffolds; use the Rust SDK for executable application flows.

Audit generated Rust apps

Immediately inspect every generated Cargo.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:
If a required fix is not published, pin both Stoffel crates to the official repository and a full 40-character revision. Keep them on the same revision:
An adjacent path such as 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:
Audit 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:
Repository scripts must derive their root from the script file; callers may invoke them from any directory:

Inputs

Named function inputs use repeated --input flags:
ClientStore inputs use repeated --client-input flags. Repeating the same slot appends values in order for that client:
Do not pass comma-separated assignments like --input a=1,b=2.

Input files

Both named inputs and ClientStore inputs can be loaded from .json, .csv, or .txt. Named inputs:
Formats:
ClientStore inputs:
Formats:
Values may be integers, unsigned integers where supported, booleans, strings, JSON arrays/objects, or 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:
If tests exist:
For secret examples copied from the repository, use the exact first-line # run-args: header when present.

Common pitfalls

  • stoffel run --config expects network/off-chain config, not project Stoffel.toml.
  • stoffel init creates 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, use stoffel status or stoffel 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.

Next playbooks