Skip to content

Latest commit

 

History

History
339 lines (246 loc) · 22.7 KB

File metadata and controls

339 lines (246 loc) · 22.7 KB

CLI

The CLI is intentionally thin. It delegates config, artifacts, command execution, and parser behavior to @caatinga/core.

Supported today vs not yet

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 identity

Notes:

  • caatinga setup is available on @caatinga/cli@latest (3.4.0+).
  • The Stellar CLI is version-pinned to the last-tested release so caatinga doctor never 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 install can take 5–15 minutes (compiling from source). Faster alternatives: cargo binstall stellar-cli or 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.
  • During cargo install stellar-cli, you may see warning: package slipped10 … is yanked from 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.exe instructions instead of failing cryptically.
  • On a non-testnet/non-fundable network (for example mainnet), 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" so cargo and stellar resolve 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).

caatinga init <projectName>

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 (use caatinga 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 --minimal

caatinga build [contract]

Builds 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.

caatinga wire [--network testnet] --source <identity>

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.

caatinga sync-env [--network testnet]

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.

caatinga generate [contract] [--network testnet] [--strict-network]

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.

caatinga status [--network <name>] [--json] [--strict]

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.

caatinga smoke [--network testnet] [--source alice]

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 testcaatinga buildcaatinga deploy --if-changedcaatinga generatecaatinga smoke.

caatinga ci run [--network testnet] [--source alice] [--strict] [--skip-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.

caatinga identity export [--path ~/.config/stellar]

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.

caatinga identity import <archive-file> [--path ~/.config/stellar]

Imports a base64-encoded tarball file produced by caatinga identity export (not a raw binary path).

caatinga invoke <contract.method> --source <identity> [--network testnet] [args...]

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).

Expect DSL

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"}' --summary

Full schema and config examples: Config — postDeploy and smoke.

ZK commands

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-vk on zk build — experimental; writes vk.rs only. zk invoke --embed-vk is 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.

Stellar CLI compatibility

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).

Current limits

  • --source must be a local Stellar CLI identity alias that can sign transactions. Public G... addresses, secret keys, and seed phrases are rejected.
  • caatinga dev is reserved and hidden in pre-v1 builds. Use your frontend dev server (for example Vite) alongside caatinga build, deploy, generate, and invoke.
  • CLI XDR commands and caatinga generate --interop are not implemented yet.

Error codes

Caatinga emits public CAATINGA_* error codes for automation. Common examples:

  • CAATINGA_CONFIG_NOT_FOUND
  • CAATINGA_INVALID_CONFIG
  • CAATINGA_STELLAR_CLI_NOT_FOUND
  • CAATINGA_CONTRACT_ID_NOT_FOUND
  • CAATINGA_SOURCE_ACCOUNT_REQUIRED
  • CAATINGA_TEMPLATE_MANIFEST_NOT_FOUND
  • CAATINGA_TEMPLATE_INCOMPATIBLE
  • CAATINGA_XDR_BUILD_FAILED
  • CAATINGA_XDR_SIGN_FAILED
  • CAATINGA_ZK_VERIFICATION_FAILED

See docs/errors.md for the full table.