> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stoffelmpc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Stoffel CLI App Workflow

> Use the stoffel CLI to init, check, build, compile, run, test, inspect, and troubleshoot Stoffel apps.

> 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

```sh theme={null}
stoffel init my-app          # alias: stoffel new my-app
stoffel status --verbose     # alias: stoffel doctor --verbose
stoffel check                # validate source and project MPC settings
stoffel build                # build bytecode under target/debug/
stoffel build --release      # build bytecode under target/release/ and default to O3
stoffel compile src/main.stfl --output target/debug/app.stflb
stoffel compile --disassemble target/debug/app.stflb
stoffel run                  # local MPC testing by default unless --network/--config is set
stoffel dev --once           # one build+run pass; omit --once for watch mode
stoffel test --verbose       # run no-argument Stoffel test functions
stoffel clean --dry-run
stoffel update --check       # alias: stoffel upgrade --check
```

`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`:

```toml theme={null}
[package]
name = "my-app"
version = "1.0.0" # your app package version
authors = []

[mpc]
backend = "honeybadger"
parties = 5
threshold = 1
# instance_id = 0
# curve = "bls12_381"       # optional alias: field; mainly for AVSS backend

[build]
source = "src/main.stfl"    # or "src" for a source directory
target_dir = "target"       # alias: output_dir
# optimization_level = 2
```

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:

```sh theme={null}
stoffel check --backend honeybadger --parties 5 --threshold 1
stoffel build --backend avss:bls12_381
stoffel build --backend avss:bn254
stoffel build --backend avss:curve25519
stoffel build --backend avss:ed25519
stoffel build --backend avss:secp256k1
stoffel build --backend avss:p-256
```

`--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:

```sh theme={null}
stoffel init my-app                         # default Stoffel app + Rust wrapper files
stoffel init my-lib --lib                   # library-style Stoffel source
stoffel init my-rust-app --template rust    # Rust app wrapper with nested stoffel/ project
stoffel init my-python-app --template python
stoffel init my-foundry-app --template solidity-foundry
stoffel init my-hardhat-app --template solidity-hardhat
```

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:

```toml theme={null}
[dependencies]
stoffel = { package = "stoffel-rust-sdk", version = "<current-docs-version>" }

[build-dependencies]
stoffel-bindgen = "<current-docs-version>"
```

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:

```toml theme={null}
[dependencies]
stoffel = { package = "stoffel-rust-sdk", git = "https://github.com/Stoffel-Labs/stoffel.git", rev = "<full-40-character-commit-sha>" }

[build-dependencies]
stoffel-bindgen = { git = "https://github.com/Stoffel-Labs/stoffel.git", rev = "<full-40-character-commit-sha>" }
```

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:

```sh theme={null}
APP_MANIFEST="/absolute/path/to/generated-app/Cargo.toml"
cargo generate-lockfile --manifest-path "$APP_MANIFEST"
cargo check --locked --manifest-path "$APP_MANIFEST"
cargo test --locked --manifest-path "$APP_MANIFEST"
cargo metadata --locked --format-version 1 --manifest-path "$APP_MANIFEST" \
  > "${APP_MANIFEST%/*}/cargo-metadata.json"
```

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:

```sh theme={null}
PROOF_DIR="$(mktemp -d)"
APP_COMMIT="<reviewed-app-commit-sha>"
git clone "<generated-app-repository-url>" "$PROOF_DIR/app"
git -C "$PROOF_DIR/app" checkout --detach "$APP_COMMIT"
cargo check --locked --manifest-path "$PROOF_DIR/app/Cargo.toml"
```

Repository scripts must derive their root from the script file; callers may invoke them from any directory:

```sh theme={null}
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
APP_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)"
STOFFEL_ROOT="$APP_ROOT"
if [ ! -f "$STOFFEL_ROOT/Stoffel.toml" ] && [ -f "$APP_ROOT/stoffel/Stoffel.toml" ]; then
  STOFFEL_ROOT="$APP_ROOT/stoffel"
fi
test -f "$STOFFEL_ROOT/Stoffel.toml"
stoffel check "$STOFFEL_ROOT"
cargo check --locked --manifest-path "$APP_ROOT/Cargo.toml"
```

## Inputs

Named function inputs use repeated `--input` flags:

```sh theme={null}
stoffel run src/main.stfl --input a=40 --input b=2
```

ClientStore inputs use repeated `--client-input` flags. Repeating the same slot appends values in order for that client:

```sh theme={null}
stoffel run examples/mpc_top_k/main.stfl \
  --client-input 0=50 --client-input 0=20 --client-input 0=40 \
  --client-input 0=10 --client-input 0=30 \
  --expected-output-clients 1
```

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:

```sh theme={null}
stoffel run --input-file inputs.json
stoffel run --input-file inputs.csv
stoffel run --input-file inputs.txt
```

Formats:

```json theme={null}
{"a": 40, "b": 2}
```

```csv theme={null}
a,b
40,2
```

```txt theme={null}
# one name=value per line
a=40
b=2
```

ClientStore inputs:

```sh theme={null}
stoffel run --client-input-file client-inputs.json --expected-output-clients 1
stoffel run --client-input-file client-inputs.csv --expected-output-clients 1
stoffel run --client-input-file client-inputs.txt --expected-output-clients 1
```

Formats:

```json theme={null}
{"0": [40, 2], "1": [7]}
```

```csv theme={null}
slot,value
0,40
0,2
1,7
```

```txt theme={null}
# repeated slots append in order
0=40
0=2
1=7
```

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

```sh theme={null}
stoffel build --program-info        # build stats are printed after bytecode write
stoffel run target/debug/app.stflb --program-info
stoffel compile --disassemble target/debug/app.stflb
```

`--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:

```sh theme={null}
stoffel status --verbose
stoffel check
stoffel build
stoffel run --timeout-secs 180
```

If tests exist:

```sh theme={null}
stoffel test --verbose
```

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

* [Stoffel-Lang App Programming](/developer-skills/stoffel-lang-app-programming)
* [Stoffel Secret MPC Programming](/developer-skills/stoffel-secret-mpc-programming)
* [Stoffel Local MPC Dev Loop](/developer-skills/stoffel-local-mpc-dev-loop)
* [Stoffel App Troubleshooting](/developer-skills/stoffel-app-troubleshooting)
