Repository navigation
feat: config-driven templates with testnet as staging - #282
Merged
Merged
Conversation
The frontend's network now comes from the passphrase and RPC URL the CLI
writes into app-lib/clients, so it can't drift from the network the
contracts were built for. An unknown passphrase throws instead of
falling back to local. Balances come from RPC instead of Horizon;
`MappedBalances` is now `{ xlm?: { balance } }` and `horizonUrl` is
no longer exported.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb
Testnet no longer deploys from `build` or `watch`; contracts point at deployments made deliberately. A commented `testnet-dev` network shows how to opt in to redeploying on testnet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb
`npm start` runs `stellar scaffold watch` without `--build-clients`, which a version 2 scaffold.yml no longer needs. .env.example drops the PUBLIC_STELLAR_* values and the per-project XDG_CONFIG_HOME, keeping an optional STELLAR_NETWORK and a slot for secrets. CI keeps the flag for released CLIs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb
`stellar scaffold build` records deployments in .scaffold/state.json. The directory ignores itself for git, but Prettier only reads the root .gitignore, so `prettier --check .` flagged the generated file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb
The generated clients index also exports a shared `options` object, so counting every `export const` overcounted by one and failed the check even when every client was generated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* If the defaults only apply to one network, just put them in that network * If the comments for the `testnet` network below make it hard to tell where the indent level should go, leave a `testnet` example in, even if the contract ID is invalid (it still typechecks, but will fail on build; there's a comment explaining what to do)
chadoh
previously approved these changes
Oct 16, 2026
chadoh
left a comment
Contributor
There was a problem hiding this comment.
A couple small comments & suggestions, but overall it looks great! No need for re-review after (optionally) addressing the suggestions below.
Co-authored-by: Chad Ostrowski <221614+chadoh@users.noreply.github.com>
zachfedor
added a commit
to stellar-scaffold/cli
that referenced
this pull request
Oct 17, 2026
Restores Scaffold's local-first model: **local** is for experimenting freely, **testnet** is staging and a deliberate dry run, and **mainnet** is copied over when it's ready. `build` follows `scaffold.yml` instead of flags, and each checkout of a project keeps its own record of what it deployed, so projects and worktrees that share stellar-cli's global config no longer reuse each other's contracts. Companion UI PR: stellar-scaffold/ui#282 (same branch, `feat/config-driven-network`). Both PRs carry the `cross-repo` label so each one's CI builds against the other. ## Changes **Network selection** - Precedence is `--network`, then `STELLAR_NETWORK`, then `stellar network use`, then `local`. - `build` now says when the network came from `stellar network use`, and `config show` resolves the network the same way `build` does. - "Not deploying" messages name the network. **`build` with a version 2 `scaffold.yml`** - Always deploys and generates clients for networks that allow deploys. `--build-clients` is accepted but only prints a note. - `init` without a frontend and `upgrade` only compile. **`.scaffold/state.json`** (new `state` module) - Records, for each network, the contract ID and saved alias of each deployed contract. The format version is independent of `scaffold.yml`'s. - Machine-local: `.scaffold/` ignores itself with its own `.gitignore`. Writes are atomic. - `build` decides between deploying, upgrading and reusing from this record, not from stellar-cli's global aliases. - If a network name is redefined with a different passphrase, the entries recorded for it are dropped. **Aliases** - Scaffold saves aliases itself as `<directory>-<contract>` (e.g. `my-app-guess_the_number`) and no longer passes `--alias` to `stellar contract deploy`. Separate checkouts and worktrees get separate aliases. - It only overwrites an alias that's free or already its own. Otherwise it warns and prints the `stellar contract alias remove` command. - After the project directory is renamed, the next deploy removes the old alias. **`clean`** - Removes only the recorded aliases that still point at the recorded contracts, then deletes `state.json`. - No longer removes keys, which may be shared with other projects. **Docs** - Configuration and CLI reference, the tutorial, and the agent skill are updated for all of the above. ## Upgrading (release note) > Scaffold now records deployments in `.scaffold/state.json` and no longer finds them through contract-name aliases like `guess_the_number`. The first build after upgrading deploys every contract again, on every network you build for. Later builds upgrade them as usual. Old aliases are left in your stellar-cli config; remove them with `stellar contract alias remove <name>`. New aliases are prefixed with the project directory name (e.g. `my-app-guess_the_number`). ## Known limitations - Two checkouts with the **same directory name** share an alias prefix. The second one gets the "Not saving alias" warning, and its contracts are still tracked correctly in its own `state.json`. - Spanish translations under `docs/site/i18n/es` still use the old paths and aliases. ## Testing - `cargo fmt`, `cargo clippy --workspace --all-targets --all-features`, and the unit tests (239) pass, including new tests for the state file, alias naming, alias ownership, and `clean`. - Before rebasing onto 0.0.29, the full integration suite passed 269/269 against local quickstart (protocol 29). New test: `checkouts_sharing_a_stellar_config_keep_their_own_contracts`, which fails on `main` because the second checkout reports the first checkout's contract as up to date. - Manual run against the UI branch with `stellar scaffold build`: - The first build deployed all three contracts and saved `ui-*` aliases. - The second build reported them up to date. - `contract invoke --id <alias>` worked. - `clean` removed the aliases and the state file and kept the keys. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion to stellar-scaffold/cli#630. The templates now rely on
scaffold.ymlto decide what gets deployed where, use stellar-cli's global config, and treat testnet as staging.Merge after the CLI release that includes #630. This PR carries the
cross-repolabel, so its CI builds the CLI fromfeat/config-driven-network.Changes
app-libMappedBalanceschanges shape.scaffold.ymltestnet-devexample shows how to opt in to automatic testnet deploys.Templates
startrunsstellar scaffold watchwithout--build-clients, sincescaffold.ymlnow decides. CI keeps the flag..env.exampledropsXDG_CONFIG_HOME/STELLAR_CONFIG_HOME, so keys and aliases live in stellar-cli's global config. It keeps a commentedSTELLAR_NETWORK, a slot for secrets, and a note onPUBLIC_variables..scaffold(the CLI's machine-local deployment record) is added to.gitignoreso Prettier skips it.CLAUDE.mdare updated.Known follow-ups
STELLAR_NETWORK=testnet npm startfails until a testnettype: contractentry exists, because testnet no longer deploys.build.ymlstill writes.config/stellar/identity/me.toml, which nothing reads now.dapp-ipfs.ymlis out of date.Cargo.lockdoesn't match the contracts: a build bumps the contract crates from 0.0.1 to 0.0.2. This predates this PR.Testing
npm run lintandnpm run format:checkapp-libtypecheckui-*aliases.cleanremoved the aliases and the state file.🤖 Generated with Claude Code
https://claude.ai/code/session_01QhmaWLv4yExX8LahP5UtUb