What the wizard does, step by step
The wizard's step sequence in order — what each step asks, what answers it takes non-interactively, what it writes, and which ones reach your Chatfuel or Supabase account.
Every command-line mistake is answered before the first question, so a mistyped --logo or a
--supabase-project paired with --supabase-create costs you nothing but the typing. A run that
has questions and nothing attached to the terminal is refused in the same place, before anything
is asked or spent, and a credential passed as a flag earns one line naming the environment
variable that does the same job without putting it in ps.
The sequence
| Step | What it asks | Answered non-interactively by | What it writes |
|---|---|---|---|
| Welcome | Nothing. The banner animates only for a person on a TTY. | — | — |
| Flag checks | Nothing. The auth, brand, agent, admin, app and origins flags are judged here, before anything is spent. | — | — |
| Preflight | Nothing. Checks Node against the floor of 22.19.0, resolves the package manager, and records which agent CLIs are on PATH. | — | — |
| Resolve content | Nothing. Asks the repository what the branch points at now and settles which commit this run installs from. A failure here is not a failure of the run: it falls back to the commit the wizard shipped with, and says which wall it hit. | CHATFUEL_CONTENT_REF pins a commit or names another branch. | — |
| Resolve app | Nothing, unless the catalog is not the official one — then a confirm. Clones the catalog, reads the preset's manifest, playbook and logo, and prints the modules, the npm dependencies and the files it will add. | --app, with --apps-repo / --apps-ref or CHATFUEL_APPS_REPO. Under --yes a catalog named by --apps-repo is fetched with a warning; one named only by CHATFUEL_APPS_REPO is refused. | A temporary clone, removed when the run ends. |
| Mode | New app, or embed into the project you are standing in. | --embed. Plain --yes stays standalone, and --app is standalone by definition. | — |
| Modules | Which modules you want, then whether to add the ones your selection recommends. | --modules, or the preset. Under --yes, every ready module except auth and admin. Recommendations are named rather than offered whenever the list came from a flag or a preset. | — |
| Fetch the content | Nothing. Downloads what this module set needs from the resolved commit into the cache, checking every byte against its digest. A second run against the same commit takes them from the cache and asks the network for nothing. | — | The wizard's own cache, not your project. |
| Agent | Which coding agent finishes the setup — asked only if both are installed. | --agent; --yes takes the first one detected. | — |
| Skills target | Into the project, or into your home directory. | Nothing; --yes takes the project. | — |
| Token | Your Chatfuel token, masked, then checked against the API. A rejected token is re-asked, up to three times. | CHATFUEL_TOKEN in the environment. | Held in memory until the scaffold writes .env. |
| Workspace | Which Chatfuel workspace this deployment starts in. Taken silently when the account owns one. With auth it also says how much room the workspace has left for bots. | --workspace | VITE_CHATFUEL_WORKSPACE_ID, and CHATFUEL_WORKSPACE_ID as well when auth is installed. |
| Trial | Nothing, if the workspace is already subscribed. Otherwise which plan — Business or an Agency tier, each line with its monthly price, its AI credits and its bot limit — then it prints a checkout link for that plan and waits, offering a way out every five minutes. Nothing opens a browser: the link is yours to follow when you are ready. | --pricing; --yes takes Business, prints the link and moves on without a plan. | — |
| Brand | What the app is called, and a path to a logo file. Standalone only, and prompt-free with --app. | --app-name, --logo, or the preset's brand. | Both land in files the scaffold step then writes. |
| Auth setup | Only with the auth module: access token or manual, then the project, then who may sign up, whether admins may issue recovery links, and the deployed origin. | --supabase-token / SUPABASE_ACCESS_TOKEN with --supabase-project or --supabase-create, or --supabase-url with --supabase-anon-key; --signup; --app-url. | VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, SUPABASE_PROJECT_REF, and AUTH_RECOVERY_LINK_LOG when it is turned on. |
| Admin setup | Only with the admin module: whether to set your own password. | --admin-password, ADMIN_PASSWORD, else a generated one. | ADMIN_PASSWORD. |
| Origins | Which browser origins may call the proxy: the app's own, a list you name, or every origin. | --allowed-origins, or ALLOWED_ORIGINS. --yes leaves it at the app's own origin. | ALLOWED_ORIGINS, when the answer is not same-origin. |
| Scaffold | Where to create the app. A directory that exists and is not empty is refused. | --dir | The app: the template copied, unselected module subtrees deleted, the module registry regenerated, the nav table filtered, the design system, the API client, the schema and the proxy vendored as sources, the operation documents and the generator copied in beside them, the proxy imports rewritten in all three hosts, the package renamed, a preset's overlay applied, the auth migrations written, .env at mode 0600, .chatfuel/lock.json, the skills, and an install. |
| Embed | Nothing beyond a confirm to install the dependencies. Replaces the scaffold step when the mode is embed. | Nothing; --yes declines the install. | src/chatfuel/ in the host, the auth SQL under supabase/chatfuel/, the skills, .chatfuel/lock.json, and only the .env keys the host does not already define. |
| Deploy | Whether to deploy to Vercel now, and what to call the project. A deploy that fails is offered again. | Not offered under --yes. | .vercel/project.json, by way of the app's own deploy script. |
| GitHub (questions) | Whether to put the app on GitHub, under what name, and public or private, then the sign-in. Before the name, when the deploy found that Vercel has no GitHub connection, it says so and asks whether you have added it — a no carries straight on. | Not offered under --yes. | Nothing yet — this half reaches neither GitHub nor the working tree. |
| Handoff | Whether to install a coding agent, when none is on PATH. | Nothing; --yes writes the files and installs nothing. | CLAUDE.md or AGENTS.md, and the setup checklist at the path that agent reads it from, both recorded in the lock. In embed mode the instructions file gets a marked section refreshed rather than being overwritten. |
| GitHub (push) | Nothing, unless a push was interrupted before — then whether to finish it, and whether a push should redeploy. That last question is skipped when Vercel still has no GitHub connection: there is nothing for the repository to hang off, so the run says a push will not redeploy and names connect-git to run later instead of asking. | Not offered under --yes. | A git repository, a first commit, an origin. |
| Outro | Nothing. Prints the next steps, the trial, the sign-in facts, any skills left at the version they had, and a generated admin password. | — | — |
| Launch the agent | Whether to start the agent in the new app. | Not offered under --yes or --dry-run. | — |
| Launch | Whether to start the dev server and open the browser. Standalone only, and never after a handoff. | Not offered under --yes or --dry-run. | — |
Under --plan nothing in that last column is written. Every question is still asked and the run
prints each file it would have made, with its path.
The order is not alphabetical and not arbitrary. The content is resolved first, because the module
picker reads manifests and a module added since this wizard was published is one nobody could
otherwise choose. The download comes after the picker, because what has to be fetched is only known
once the modules are. The agent is settled before anything is copied, because Claude Code and Codex
read skills from different directories. The trial comes before anything is written, because a
workspace with no plan produces an app that answers nothing. Deploy and the GitHub questions come
before the handoff, because both need the terminal — the Vercel login and gh auth login are
conversations — and a handoff can give the terminal to an agent session; the commit and the push
wait until after it, because the handoff is still writing the app.
What reaches an account
| Step | What it does to your account | Stopped by --dry-run |
|---|---|---|
| Token | Reads the current user, to check the token. | No — it creates nothing. |
| Workspace | Creates a Chatfuel workspace, but only when the account owns none. | Yes — the run carries a stand-in that exists nowhere else, and every step that would spend it is guarded too. |
| Trial | Opens a Stripe checkout session on the workspace. | Yes. |
| Auth setup | Creates a Supabase project, runs the migrations, patches the auth config and the recovery email template. | Yes — each is printed as the call it would have made. |
| Deploy | Creates a Vercel project and a deployment. With the auth module on the access-token path it then adds the deployed origin to the Supabase redirect allowlist; on the manual path it prints the line for you to add by hand. | Yes — the step is skipped entirely. |
| GitHub | Creates a repository under your account and pushes to it. | Yes — the step is skipped entirely. |
Everything else is local. --dry-run does not stop the scaffold: the app is written to disk, its
lock beside it, and its dependencies installed either way. --plan is the flag that stops that too.
A workspace with no subscription has no AI. The bot answers nothing, and the finished app reads as a broken scaffold — which is why the trial step blocks rather than warns, and why a run that ends without a plan is told again in the closing summary.
Ctrl+C
Press it and the run stops where it is, after undoing what it had half-written. Each step registers what it wants undone while it is inside its own dangerous window and releases it on the way out, so the handler always knows exactly what is half-written at the moment the signal lands. The cleanups run newest first, and one that fails does not take the others with it.
What that means in practice: an app directory this run created is removed, so the same command can
be run again — a directory that was already there is described and left exactly as it is, because
nothing can tell your files from ours. In embed mode the src/chatfuel/ root this run created goes
and the host's own files stay, with anything written outside it named rather than deleted. A clone
of the apps catalog is deleted. An interrupted update writes down which files it had already
copied. The exit code is 130, as it is for any process a shell interrupts, and 143 for SIGTERM.
The CLI
Every command and flag of npx @chatfuel/wizard, what each one falls back to when you omit it, which answers come from the environment, what --yes, --dry-run and --plan refuse to do, and the exit codes.
The environment the wizard reads and writes
Every variable the wizard itself reads, the .env and .env.example it leaves behind, the lock it writes beside them, what --embed appends instead of overwriting, and the guard that refuses to persist a token.