StackPanel

stack setup

Reconcile the project - report, confirm, apply

stack setup

Show the same report as stack doctor, decide pending adoption offers, preview what adopting them generates, then apply everything after confirming. Think terraform apply: it shows the plan first.

On a directory that is not a stackpanel project yet, setup first writes the scaffolding (flake.nix, .envrc, .stack/) from the stackpanel flake's lib.initTemplates.<template> - the same file set nix flake init -t copies - and registers the project with the agent. Existing files are left alone unless --force. With a unified reconciler there is no difference between initializing a project and reconciling one from empty, so this command replaces the former stackpanel init.

The flow

  1. Diagnose. Every reconciler runs read-only: scaffold, codegen, files, fileops, checks, addons, register. The report is rendered.
  2. Decide offers. Each pending adoption offer is asked once (or answered by --yes, --with, --without, --addon). Declining records "shown, said no" in .stack/reconcile.json and writes nothing else.
  3. One speculative evaluation. The accepted config mutations are overlaid on the module system and the resulting files.entries are diffed against disk. One evaluation for the whole accepted set, none if nothing was accepted. Pure: nothing is written or built.
  4. Confirm, then apply: scaffolding and registration, generated files, file ops, then the config mutations. When a mutation was written, the new generation's write-files and preflight manifest are realized with nix build and run, so the adopted module's files materialize without re-entering the shell.

Adoption is one-way: the reconciler cannot undo it, because config is the input that decides what the reconciler does. Undoing adoption is an edit of .stack/config.nix.

Usage

stack setup                                 # interactive
stack setup --yes                           # take every default, no prompts
stack setup --json                          # print the plan, apply nothing
stack setup --only files                    # reconcile generated files only
stack setup --with playwright               # accept an offer without prompting
stack setup --without editorconfig          # decline an offer without prompting
stack setup --addon deploy=fly              # answer a select offer explicitly
stack setup --reconsider                    # re-offer declined addons
stack setup --flake path:/path/to/sp        # scaffold from a local checkout
stack setup --tmp                           # scaffold into a temporary git repo

Flags

FlagTypeDefaultDescription
--yes, -yboolfalseSkip confirmation and take every default answer
--jsonboolfalsePrint the plan as JSON and exit without applying
--dry-runboolfalseShow the report and exit without applying
--onlystringsnoneRun only these reconcilers (repeatable)
--skipstringsnoneSkip these reconcilers (repeatable)
--reconsiderboolfalseRe-offer addons that were declined at their current revision
--forceboolfalseOverwrite existing scaffolding files and rewrite generated files
--flakestringnoneStackpanel flake reference used for scaffolding (default: github:darkmatter/stackpanel)
--templatestringdefaultScaffolding template name
--tmpboolfalseCreate the project in a temporary git repository and print its path
--non-interactiveboolfalseNever prompt (same as --yes)
--withstringsnoneAccept an addon by id without prompting (repeatable)
--withoutstringsnoneDecline an addon by id without prompting (repeatable)
--addonstringsnoneAnswer an addon explicitly as id=value (true/false, a choice value, or comma-separated values)
--buildboolfalseAlso realize build-scope doctor checks with nix build

The discovery ledger

.stack/reconcile.json records what the user has been shown at which revision:

{ "version": 1, "seen": { "playwright": { "revision": 1, "answer": false, "at": "2026-09-04T01:22:11Z" } } }

An offer is re-shown only when its author bumps revision, or with --reconsider. .stack/addons.json from older releases is migrated automatically.

Global Flags

These flags are inherited from parent commands.

FlagTypeDefaultDescription
--daemon, -dboolfalseRun in daemon mode (no TUI, for background processes)
--no-colorboolfalseDisable color output
--no-tuiboolfalseDisable interactive TUI mode
--verbose, -vboolfalseEnable verbose output

On this page