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
- Diagnose. Every reconciler runs read-only:
scaffold,codegen,files,fileops,checks,addons,register. The report is rendered. - Decide offers. Each pending adoption offer is asked once (or answered by
--yes,--with,--without,--addon). Declining records "shown, said no" in.stack/reconcile.jsonand writes nothing else. - One speculative evaluation. The accepted config mutations are overlaid
on the module system and the resulting
files.entriesare diffed against disk. One evaluation for the whole accepted set, none if nothing was accepted. Pure: nothing is written or built. - Confirm, then apply: scaffolding and registration, generated files,
file ops, then the config mutations. When a mutation was written, the new
generation's
write-filesand preflight manifest are realized withnix buildand 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
stack setup --experimental-agent=auto # discover an installed coding agent
stack setup --experimental-agent=codex --yes # accept its onboarding plan automaticallyExperimental agent onboarding
--experimental-agent delegates repository inspection and configuration to an
installed coding agent, then verifies the result with stack doctor.
Codex and Claude Code are supported when their installed versions expose the
required automation and permission controls. OpenCode is discovered but currently
reported as unsupported. Agent discovery does not establish authentication;
authenticate the chosen CLI before running setup. Its configured model and
authentication are reused.
With auto, a single supported agent is selected automatically. Multiple agents
produce a picker in an interactive terminal; noninteractive runs must select one
explicitly. --yes and --non-interactive accept the proposed onboarding plan.
The wizard uses the CLI's shared terminal theme, with a stage indicator, elapsed time, and a scrollable plan. Use arrow keys to choose, Space to toggle multiple selections, and Enter to continue. Text answers support cursor editing and paste. PgUp/PgDn scroll the plan while Apply, Revise, and Cancel remain visible. Ctrl+D shows recent agent activity during setup; Esc or Ctrl+C cancels.
The wizard asks questions when choices are unresolved and lets you apply, revise,
or cancel a concrete plan. Question rounds preserve
previous answers and do not consume the single doctor repair attempt. --yes
and noninteractive runs use declared defaults; a required question without a
default stops with an actionable error. Full provider event logs are available
through --agent-log /path/to/new-log.jsonl (created privately, never overwritten).
On resume, an existing log is preserved and a new sibling .resume-*.jsonl log is created.
If a completed agent response contains malformed JSON, setup saves that reply and requests one read-only formatting correction. This does not repeat repository edits or consume the doctor repair attempt. The corrected response must pass the same validation; a proposed plan still requires review and doctor still verifies setup. Provider failures, permission denials, and semantic validation errors are not treated as formatting errors. If correction fails, rerunning setup retries the saved reply.
The agent first inspects the repository without writing and returns a concrete
plan with configuration expectations. After acceptance, Stackpanel writes missing
scaffold files from the already-fetched template. The sandboxed agent then edits
the repository's flake, apps and commands. Stackpanel creates or updates
flake.lock on the host, where the Nix daemon is accessible. The agent does not
run Nix, enter a devshell, or invoke scaffolding itself. Setup keeps expectations fixed
through the rest of the run. Explicit addon selections become configuration
assertions too; in this experiment --without requires the addon's enable switch
to be false. Unknown addons and choices are rejected. Git framework sources are
pinned. Dirty local framework checkouts are rejected: omit --flake or select a
committed revision with git+file:///absolute/path?rev=<commit>. This avoids
copying ignored local state into the Nix store through directory inputs.
The resulting repository must contain flake.lock.
The host supplies repository-onboarding option names, types, and descriptions
from the pinned framework's lib.getOptions, including Nix-only app tooling and
command fields omitted by starter templates. This lookup uses pure Nix evaluation
independently of the target repository, so a broken configuration can still be
repaired. Older saved sessions gain this schema before the next agent invocation;
their answers, accepted plan, template, and framework revision are retained.
Stackpanel then enters a fresh Nix shell, reconciles generated files, and runs:
stack doctor --strict --scope repo,build --build --expectations /path/to/expectations.json --jsonOnly doctor determines success. Failed input locking, reconciliation, or verification is sent back for one repair attempt, followed by another fresh reconciliation and doctor run. Checks observed on the first doctor run are also required during repair, so removing a failing check cannot make repair pass. Unavailable required permissions, authentication failures, and agent execution failures stop the run. Claude uses native read/edit tools; shell commands run on the host. A successful Claude reply can contain denied optional reads. These are displayed as warnings and do not grant access; doctor still decides whether the agreed outputs pass. Denied edits, commands, and unknown tools still stop setup with the denied tool named in the error. Each agent or shell stage has a 15-minute deadline, and interruption cancels its subprocesses.
If the second doctor report still has findings, setup exits 0 with a warning
and leaves the session unverified and resumable. It preserves the files and
choices and prints an exact command to rerun doctor --onboarding in a fresh
devshell using the current CLI. Doctor executes the saved acceptance checks
without an agent and still exits 1 when they fail. Runtime and Studio setup
remain pending until repository verification passes. Invalid doctor reports,
failed Nix execution, and agent errors still stop setup with a nonzero exit.
--dry-run and --json retain the ordinary read-only setup report and never
launch an agent. Agent onboarding cannot be combined with --only, --skip, or
--reconsider. Shell entry still executes the repository's normal hooks, including
generation and project registration; this also applies to --tmp repositories.
Stackpanel records the initial Git index and existing dirty files. Changes to
those user edits stop verification without reverting files. New onboarding inputs
and source/manifests listed in the accepted plan are marked with
git add --intent-to-add for Git-backed Nix evaluation. These
entries remain after success so subsequent shell entry sees the files; their
contents are not staged. Verification warnings also retain these entries so
doctor can re-evaluate the repository. Other failed setup operations remove their
temporary entries. Once repository
verification passes, the entries remain even if runtime setup fails, so the
configured repository stays evaluable. Review the resulting repository diff.
Create a new repository
stack setup --experimental-agent=auto --new ./my-appThe target must be absent or empty on its first run. A saved setup can resume in
that same directory once it contains files. The wizard asks what you want to build, uses
Stackpanel templates for the environment, and generates the application starter.
New flake plans follow the framework's pinned Nix inputs unless other versions
were requested, keeping the framework and its dependencies compatible.
The reviewed plan includes required files and build/test commands. Doctor checks
those exact paths and argument arrays in the target devshell; repair cannot
replace them. --new cannot be combined with --tmp, --json, or --dry-run.
Resume an interrupted setup
Run the same command again:
stack setup --experimental-agent=auto --tmp --template minimal
# If interrupted, repeat this command from the same working directory.Setup saves a versioned JSON manifest beside the user config, normally
~/.config/stackpanel/setup/<repository-hash>.json. The wizard and errors display
the exact path. It respects XDG_CONFIG_HOME and STACKPANEL_USER_CONFIG. Files
are private, written atomically, and kept outside the repository. The manifest
records the selected agent, template and addon choices, question/answer transcript,
proposed or accepted plan, verification failures, Git fingerprints, and runtime
handoff. Malformed final replies are also saved for recovery. Full provider event
logs remain opt-in through --agent-log.
Repeating --tmp from the same directory reuses its latest unfinished repository.
Repeating --new ./my-app resumes that target. You can also enter the recorded
repository and run stack setup --experimental-agent=auto. A completed temporary
setup does not prevent the next --tmp run from creating a new repository.
Saved answers are not asked again, and an accepted plan is not reviewed again. If the agent was interrupted, it receives the choices and plan and inspects the current files to continue. If it finished generating files, setup resumes host verification without invoking the coding agent. Locking, reconciliation, and doctor run again against the current repository; saved completion markers never count as verification. A failed verification allows at most one repair per invocation, preserving the accepted expectations and previously observed checks across retries. A valid Studio handoff is reused, with live readiness checked again.
Unchanged, checkpointed setup output remains editable. New user edits and staging between runs are protected. Files changed after the last checkpoint, including output left by a hard kill, are conservatively protected too. Setup never restores files or resets Git history. A detected Git protection violation must be resolved before resuming.
Omitted configuration flags inherit saved selections. Changing --template,
--flake, or addon choices requires --restart to review a new plan. Runtime
options such as --agent-port, --studio-url, and --no-runtime=false can be
changed explicitly on retry; an explicit agent selection can also replace the
saved provider.
Use --restart to discard saved choices and plan a new setup while keeping
existing repository files. With --tmp, it creates a fresh temporary repository
and keeps the old one. Runs made before manifests were introduced cannot recover
their choices automatically; onboard the existing directory to preserve its files.
Local agent and Studio
After repository verification, setup registers the project, starts or reuses its local agent, and starts the services selected in the plan. It opens Studio and guides browser pairing. Completion requires an authenticated project configuration load and a live event connection from that browser, followed by a runtime doctor pass. Browser evidence expires and is bound to this setup session, agent, origin, and repository. Pairing uses the existing user approval page.
A running agent serving another repository is not reused: select --agent-port
or restart the agent for the intended repository. Setup-started agents continue
running with logs beside the user config in agent.log. --studio-url selects a
local or hosted Studio containing the setup handoff feature. Hosted Studio must
be updated with that feature before it can acknowledge readiness.
--no-browser verifies the local runtime and explicitly leaves Studio unverified.
--no-runtime performs repository verification only, suitable for CI. Neither
option reports browser readiness. Runtime setup does not invoke the coding agent
again or let it decide whether verification passed.
Claude Code must already permit the necessary setup shell commands; permission denials stop the experiment with the provider's diagnostic.
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--yes, -y | bool | false | Skip confirmation and take every default answer |
--json | bool | false | Print the plan as JSON and exit without applying |
--dry-run | bool | false | Show the report and exit without applying |
--only | strings | none | Run only these reconcilers (repeatable) |
--skip | strings | none | Skip these reconcilers (repeatable) |
--reconsider | bool | false | Re-offer addons that were declined at their current revision |
--force | bool | false | Overwrite existing scaffolding files and rewrite generated files |
--flake | string | none | Stackpanel flake reference used for scaffolding (default: github:darkmatter/stackpanel) |
--template | string | default | Scaffolding template name |
--tmp | bool | false | Create the project in a temporary git repository and print its path |
--non-interactive | bool | false | Never prompt (same as --yes) |
--with | strings | none | Accept an addon by id without prompting (repeatable) |
--without | strings | none | Decline an addon by id without prompting (repeatable) |
--addon | strings | none | Answer an addon explicitly as id=value (true/false, a choice value, or comma-separated values) |
--build | bool | false | Also realize build-scope doctor checks with nix build |
--new | string | none | Scaffold a new repository in an absent or empty directory |
--studio-url | string | hosted Studio | Studio URL for the browser handoff |
--agent-port | int | agent default | Local agent port |
--no-browser | bool | false | Verify runtime without opening the browser |
--no-runtime | bool | false | Verify repository only |
--agent-log | string | none | Private raw provider debug log; path must not exist |
--experimental-agent | string | none | Experimental repository onboarding using auto, codex, or claude |
--restart | bool | false | Review a new agent onboarding plan; with --tmp, create a fresh repository |
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.
| Flag | Type | Default | Description |
|---|---|---|---|
--daemon, -d | bool | false | Run in daemon mode (no TUI, for background processes) |
--no-color | bool | false | Disable color output |
--no-tui | bool | false | Disable interactive TUI mode |
--verbose, -v | bool | false | Enable verbose output |