The CLI is intentionally thin. It delegates config, artifacts, command execution, and parser behavior to @caatinga/core.
| Capability | Status |
|---|---|
| Official frontend templates | Vite + React only (vite-react) |
caatinga upgrade |
In-place WASM upgrade (upload + invoke upgrade) |
caatinga deploy --upgrade |
Redeploy with new contractId + artifact history |
caatinga zk build |
Single-party dev ceremony; blocked on mainnet by default |
caatinga zk invoke --embed-vk |
Not supported (experimental / end-to-end incomplete) |
Browser invoke via wallet |
Single-invoker only until v1.0 |
Multi-signer / signAuthEntry |
Application code; CAATINGA_MULTI_AUTH_REQUIRED |
| Production ZK (MPC powers-of-tau) | Out of scope; no Caatinga command for MPC ceremony |
See Client and ZK module for details.
caatinga setup [--source alice] [--network testnet] [--skip-rust] [--skip-stellar] [--skip-identity]
One-step bootstrap of every prerequisite for Stellar/Soroban development. Run it before
caatinga init on a fresh machine — it detects what is missing and installs only that. Each of the
five steps is idempotent: anything already present and compatible is reported and skipped.
| Step | What it does |
|---|---|
| 1. Node.js | Verifies Node meets the minimum (22+). Cannot auto-install Node — aborts with upgrade guidance if too old. |
| 2. Rust toolchain | Installs Rust via verified rustup-init download (HTTPS + SHA256 checksum + host allowlist) when missing, or updates it via rustup update when below the minimum. |
| 3. WebAssembly target | Adds the wasm32v1-none target required to build Soroban contracts. |
| 4. Stellar CLI | Validates the installed CLI against the supported minimum; installs the last-tested version (cargo install --locked stellar-cli --version <pinned>) when missing or too old. |
| 5. Local identity | Generates the --source identity; funds it via friendbot on fundable networks (testnet, futurenet, local, standalone). |
caatinga setup # alice on testnet, install everything missing
caatinga setup --source bob --network testnet
caatinga setup --skip-rust --skip-stellar # only create the local identityNotes:
caatinga setupis available on@caatinga/cli@latest(3.4.0+).- The Stellar CLI is version-pinned to the last-tested release so
caatinga doctornever reports an untested version after setup. An already-installed CLI below the supported minimum is reinstalled at the pinned version. - On Linux, the first Stellar CLI install via
cargo installcan take 5–15 minutes (compiling from source). Faster alternatives:cargo binstall stellar-clior a prebuilt release binary. - If the Stellar CLI build from source fails, install system headers first:
- Debian/Ubuntu:
sudo apt install build-essential pkg-config libssl-dev libudev-dev libdbus-1-dev - Fedora:
sudo dnf install gcc pkg-config openssl-devel systemd-devel dbus-devel - Setup also prints these commands in the error message, plus a
cargo binstall/prebuilt-binary alternative.
- Debian/Ubuntu:
- During
cargo install stellar-cli, you may seewarning: package slipped10 … is yankedfrom the upstream lockfile. This is advisory and does not block installation. - On Windows, Rust cannot be auto-installed (the rustup flow is Unix-only) — setup prints manual
winget/rustup-init.exeinstructions instead of failing cryptically. - On a non-
testnet/non-fundable network (for examplemainnet), the identity is created but not funded — fund it manually before deploying. - When tools are freshly installed, restart your terminal or run
source "$HOME/.cargo/env"socargoandstellarresolve in the current shell. - If the Stellar CLI step fails, identity creation (step 5) is skipped automatically.
caatinga doctor is the read-only counterpart: setup installs prerequisites, doctor checks them
(plus project config, artifacts, and deploy/binding coverage).
Creates a project from a bundled template and writes caatinga.artifacts.json.
-t, --template <name> selects the template (default: react-vite-counter). Official browser templates:
react-vite-counter— single Soroban counter dApp (default)zk-starter— ZK dApp with Circom/Groth16 verifier (usecaatinga zk init <projectName>)
init validates caatinga.template.json before copying files and prints the selected template name and version.
For a step-by-step guide, see Template project. To compare template, minimal, and ZK scaffolds, see Choosing a project scaffold.
Use --minimal (or --empty) to scaffold a CLI-only project with a Soroban contract stub — no React/Vite template, no wallet stubs:
caatinga init my-contract-app --minimalBuilds one configured contract with stellar contract build. Omit contract to build every
contract listed in caatinga.config.ts (same batch semantics as caatinga deploy without a name).
When buildRoot is configured and contract is omitted, Caatinga runs a single
stellar contract build from that Cargo workspace root and then resolves each configured WASM.
Pass a contract name to keep the per-contract build behavior.
caatinga doctor [--network testnet] [--source alice] [--all-networks] [--strict] [--strict-env] [--strict-bindings]
Checks local setup before build, deploy, generate, or invoke. It validates Node.js, Stellar CLI,
Rust, wasm32v1-none, project npm dependencies (node_modules/@caatinga/core), caatinga.config.ts,
caatinga.artifacts.json, an optional configured network, and an optional local Stellar CLI identity.
With --network, doctor also compares every contract in caatinga.config.ts against
caatinga.artifacts.json for that network. Each contract prints ✓ with its contract ID when
deployed, or ✗ with a suggested caatinga deploy command when missing. Deploy coverage is
always advisory — it never blocks exit code, even with --strict.
When the deploy coverage check passes, doctor also prints a Bindings (<network>) section with
the freshness of each deployed contract's TypeScript bindings (fresh, stale, missing, or
unknown) and a suggested caatinga generate command for anything not fresh. Binding freshness
is advisory unless --strict-bindings or --strict is set.
--strict enables both --strict-env and --strict-bindings. --strict-env fails when
frontend.envFile drifts from caatinga.artifacts.json (fix with caatinga sync-env).
WASM drift and postDeploy alias advisories are always advisory — they print warnings but never
change exit code. Doctor may also print a version matrix including soroban-sdk from each
contract's Cargo.toml. Use --all-networks for a per-network deploy/bindings matrix.
caatinga deploy [contract] --source <identity> [--network testnet] [--force] [--upgrade] [--if-changed] [--no-deps] [--verify-deps] [--no-stale-check] [--no-generate] [--no-wire] [--no-sync-env] [--allow-dev-ceremony]
Deploys one contract (or the full configured graph when contract is omitted) through Stellar
CLI and records contract IDs per network in caatinga.artifacts.json. Transient testnet failures
(for example transaction submission timeouts) are retried automatically with backoff before the
command exits with CAATINGA_DEPLOY_FAILED. Dependencies deploy first
when the selected contract lists dependsOn, unless --no-deps is passed (requires a single
contract name). Use --force to redeploy when an artifact already stores a contract ID.
Use --if-changed to skip deploy when the local WASM hash matches the artifact (redeploy only when
the build changed). Skipped contracts print [skipped] unchanged and do not call Stellar CLI.
Pass --verify-deps to confirm each dependency's contract ID exists on-chain (via
stellar contract info interface) before resolving deploy arguments.
When a contract already has a contractId in caatinga.artifacts.json for the selected network,
Caatinga prints [skipped] and does not call Stellar CLI unless --force is set. Newly deployed
contracts are labeled [deployed] with their contract IDs.
Before deploy, Caatinga compares the WASM file mtime with files under contracts/<name>/src/ (best
effort). If sources look newer than the WASM, it prints a warning and continues deploy. Use
--no-stale-check to skip this check.
After a successful deploy, Caatinga automatically generates TypeScript bindings for the
contracts it just deployed. Pass --no-generate to skip (useful in CI jobs that only deploy).
If generation fails, the deploy still succeeds (exit code 0) — the CLI prints a warning with
the recovery command npx caatinga generate --network <network>.
When deploying the full contract graph (no contract argument), Caatinga also runs configured
postDeploy wiring hooks (caatinga wire) and writes frontend.envFile when configured
(caatinga sync-env), unless --no-wire or --no-sync-env is passed.
Use deploy --upgrade (alias for --force with upgrade history reason) when you want a new
contract instance and artifact history keyed by prior contractId. For admin-gated in-place WASM
replacement on the existing contractId, use caatinga upgrade instead.
caatinga upgrade <contract> --source <identity> [--network testnet] [--if-changed] [--expected-hash <hash>] [--no-build] [--generate] [--sync-env]
Upgrades a deployed contract in-place: build (unless --no-build), stellar contract upload,
then stellar contract invoke … upgrade --new_wasm_hash <hash> on the artifact's current
contractId. The artifact keeps the same ID and records the previous wasmHash in history[]
with upgradeType: "in-place".
Use --if-changed to skip when the local WASM hash already matches the artifact. Use
--expected-hash to fail before upload when the local hash does not match. Pass --generate or
--sync-env to refresh bindings or the frontend env after a successful upgrade (opt-in; unlike
full deploy, upgrade does not run these automatically).
Requires a contract that exposes an admin-gated upgrade(new_wasm_hash) entrypoint. If invoke
fails, the CLI hints to use caatinga deploy --upgrade for redeploy-style upgrades. Upload
failures exit with CAATINGA_UPLOAD_FAILED; missing hash in CLI output uses
CAATINGA_WASM_HASH_NOT_FOUND.
Runs every postDeploy and postDeployRead hook from caatinga.config.ts in order. Each hook
calls a deployed contract method with resolved placeholders (${contracts.*.contractId},
${source.address}). Hooks with kind: "read" (or entries in postDeployRead) simulate without
signing; default kind: "invoke" submits a signed transaction.
When expect is set, stdout is verified after each hook (string equality or structural matchers —
see Expect DSL). Mismatch fails with CAATINGA_POST_DEPLOY_VERIFY_FAILED.
Use after a full deploy when wiring was skipped with --no-wire, or to re-apply authority edges
on testnet after a partial failure.
Transient failures (TxBadSeq, timeouts, connection resets) are retried automatically with
exponential backoff (2s/5s default) before failing with CAATINGA_INVOKE_FAILED.
Writes frontend.envFile from caatinga.artifacts.json using the frontend.env mapping in
config. Contract keys map to deployed contract IDs; rpcUrl and networkPassphrase map to the
selected network config. Quoted values are emitted when the network passphrase contains spaces.
Generates TypeScript bindings from the deployed contract ID via npx @stellar/stellar-sdk generate (Stellar CLI is not required). The contract name is
optional: omit it to generate bindings for every contract already deployed on the
network (read from caatinga.artifacts.json), or pass a name to generate just that one.
In all-contracts mode the command first prints the current freshness of each contract's
bindings ([fresh], [stale], [missing], or [unknown] with the reason).
Each successful generation writes a .caatinga-bindings.json marker next to the bindings
recording the source contractId, wasmHash, and network. status, doctor, and generate
use that marker to detect stale bindings after a redeploy. Deleting a bindings directory simply
resets its state to missing.
After generation, Caatinga patches each binding package's package.json so bundlers (Vite) resolve
./src/index.ts directly — you do not need to run tsc inside the generated subpackage.
Pass --strict-network to fail when the selected network has no block in caatinga.artifacts.json.
Shows, per network, every configured contract with its deployed contract ID, WASM hash,
dependencies, and binding freshness in a table. Contracts not yet deployed on the network are
listed with ✗ so you can see what's left. Without --network it reports every network present
in caatinga.artifacts.json (falling back to defaultNetwork for empty projects).
For every deployed contract whose bindings are not fresh, status prints the exact
caatinga generate command that fixes it. --json prints the full machine-readable structure
on stdout for scripts and CI.
--strict exits with code 1 when any deployed contract has bindings other than fresh.
Canonical CI check after caatinga deploy --no-generate: run caatinga status --strict and expect failure until caatinga generate runs.
Runs read-only smoke checks from smoke.reads or postDeployRead in config, using the same expect DSL as postDeploy (string equality or { matcher: "isArray" }, etc.). Default expect is { matcher: "reachable" } when omitted.
When smoke.useFreshSymbol is true, each read gets an ephemeral symbol arg for testnet writes that should not pollute shared state.
caatinga regression --source <identity> [--network testnet] [--skip-test] [--skip-build] [--skip-deploy] [--skip-generate] [--skip-smoke]
Orchestrates the recommended pipeline: pnpm test → caatinga build → caatinga deploy --if-changed → caatinga generate → caatinga smoke.
CI helper: runs caatinga doctor then caatinga smoke. Intended for GitHub Actions after
restoring Stellar CLI identity secrets. --strict is forwarded to doctor only (enables
--strict-env and --strict-bindings); it does not run status --strict.
Exports the Stellar CLI config directory as a base64 tarball on stdout (for
CAATINGA_CI_STELLAR_CONFIG_B64). Prefer this over hand-rolled tar commands — see
Testing — Stellar CLI config blob.
Imports a base64-encoded tarball file produced by caatinga identity export (not a raw binary path).
Invokes a deployed contract method that mutates state or must be signed and submitted. Extra args are forwarded to the Stellar implicit contract CLI. CLI identity aliases in named args (for example --owner alice) are resolved to G... addresses before invoke.
If Stellar CLI reports that the target is a read-only method, Caatinga suggests caatinga read (or client.read() / client.simulate() in browser code) instead of force: true.
caatinga read <contract.method> [--network testnet] [--source alice] [--expect <dsl>] [--quiet] [--summary] [args...]
Simulates a read-only contract method with stellar contract invoke --send=no. --source is optional; Caatinga resolves CAATINGA_SOURCE or defaults to alice for the simulation account.
Use read for getters and pure queries. Use invoke for increments, transfers, and other state-changing calls.
Named args in read and invoke resolve CLI identity aliases (≥3 characters, for example
--owner alice) to G... addresses before calling Stellar CLI. Prefer ${source.address} in
config hooks over raw aliases. Unresolved aliases fail with CAATINGA_ADDRESS_ALIAS_UNRESOLVED.
--expect accepts the same DSL as postDeploy (plain string or JSON matcher). Mismatch fails with
CAATINGA_POST_DEPLOY_VERIFY_FAILED. --summary / --quiet print compact output for large array
payloads (see Testnet hygiene).
Shared by postDeploy, postDeployRead, smoke.reads, caatinga read --expect, and caatinga smoke.
| Form | Example | Meaning |
|---|---|---|
| Plain string | "42" or "${source.address}" |
Exact stdout match after placeholder resolution |
{ matcher: "reachable" } |
default when expect omitted in smoke |
Non-empty stdout |
{ matcher: "equals", value: "42" } |
numeric/string equality | Same as plain string |
{ matcher: "isArray" } |
list payloads | Parsed JSON is an array |
{ matcher: "isNull" } |
optional fields | stdout is null or empty |
{ matcher: "minLength", value: 1 } |
array checks | Parsed JSON array length ≥ value |
{ matcher: "maxLength", value: 10 } |
bounded lists | Parsed JSON array length ≤ value |
{ matcher: "contains", value: "abc" } |
substring | stdout includes value |
{ matcher: "matches", value: "^C[A-Z0-9]+$" } |
regex | stdout matches pattern |
{ matcher: "jsonEquals", value: "[1,2]" } |
deep JSON | Parsed JSON deep-equals value |
CLI usage:
npx caatinga read counter.count --network testnet --expect '{"matcher":"reachable"}'
npx caatinga read token.list --network testnet --expect '{"matcher":"isArray"}' --summaryFull schema and config examples: Config — postDeploy and smoke.
Circom Groth16 workflow (caatinga zk init, build, prove, invoke). Full reference:
ZK module.
| Command | Purpose |
|---|---|
caatinga zk build [circuit] [--embed-vk] |
Compile Circom and run dev trusted setup (--embed-vk experimental) |
caatinga zk prove [circuit] |
Generate proof.json and public.json |
caatinga zk invoke [circuit] --source <identity> |
Call on-chain verify_proof (dynamic VK) |
caatinga zk invoke [circuit] --network <name> |
Target a configured network (not only defaultNetwork) |
Shared ZK flags:
--allow-dev-ceremony— bypass mainnet guardrails for dev-ceremony artifacts (not for production)--embed-vkonzk build— experimental; writesvk.rsonly.zk invoke --embed-vkis blocked until the embedded-VK contract path is complete.
When verification returns false, the CLI exits with CAATINGA_ZK_VERIFICATION_FAILED. Mainnet deploy/invoke with dev ceremony artifacts exits with CAATINGA_ZK_DEV_CEREMONY_BLOCKED unless --allow-dev-ceremony is set.
Caatinga rejects Stellar CLI versions below 23.0.0 because 22.x cannot sign stellar contract invoke. Versions newer than the last-tested 27.0.0 are accepted with a non-fatal stderr advisory and a caatinga doctor warning. See Stellar CLI Version Contract.
caatinga doctor reports advisory warnings as a (N warnings) suffix on the relevant
diagnostic line plus a code: message bullet for each one. Common codes are
STELLAR_CLI_UNTESTED_VERSION (newer than the last-tested boundary) and
STELLAR_CLI_MISSING_FEATURE (a required feature was not advertised by the installed
CLI).
--sourcemust be a local Stellar CLI identity alias that can sign transactions. PublicG...addresses, secret keys, and seed phrases are rejected.caatinga devis reserved and hidden in pre-v1 builds. Use your frontend dev server (for example Vite) alongsidecaatinga build,deploy,generate, andinvoke.- CLI XDR commands and
caatinga generate --interopare not implemented yet.
Caatinga emits public CAATINGA_* error codes for automation. Common examples:
CAATINGA_CONFIG_NOT_FOUNDCAATINGA_INVALID_CONFIGCAATINGA_STELLAR_CLI_NOT_FOUNDCAATINGA_CONTRACT_ID_NOT_FOUNDCAATINGA_SOURCE_ACCOUNT_REQUIREDCAATINGA_TEMPLATE_MANIFEST_NOT_FOUNDCAATINGA_TEMPLATE_INCOMPATIBLECAATINGA_XDR_BUILD_FAILEDCAATINGA_XDR_SIGN_FAILEDCAATINGA_ZK_VERIFICATION_FAILED
See docs/errors.md for the full table.