Skip to content
ChatfuelSDK
Reference

The environment the wizard reads and writes

The variables the wizard itself reads, the .env and .env.example it leaves behind, what --embed appends instead of overwriting, and the guard that refuses to persist a token.

This page covers the environment the wizard reads and the file it leaves behind; the variables the app itself reads at build and run time are on Environment variables.

What the wizard reads

NameWhere it is readWhat it does
CHATFUEL_TOKENThe token step, first attempt.Used instead of the prompt, and still checked against the API. Under --yes, or with no TTY, its absence — or its rejection — ends the run rather than falling through to a prompt nobody can answer.
SUPABASE_ACCESS_TOKENThe auth step, and again by the deploy step.The Supabase Management API token, when --supabase-token is not given. The deploy step reads it a second time to add the deployed origin to the redirect allowlist.
SUPABASE_SERVICE_ROLE_KEYThe auth step, manual path only.Taken from the environment instead of being asked for a second time.
ADMIN_PASSWORDThe admin step, when --admin-password is not given.Used as-is; only when neither is present does the wizard generate one.
INIT_CWDEvery path the wizard resolves.Where you were standing when you started it. A package-manager run moves process.cwd(), so --dir ./app would otherwise land inside the wrong directory.
npm_config_user_agentPreflight.Whether pnpm is even considered. pnpm is chosen only when pnpm launched the wizard and is really installed; otherwise npm, which ships with Node.
https_proxy, http_proxy, all_proxy, no_proxyEvery outbound call the wizard makes, in lowercase and uppercase.Node's built-in fetch ignores these, so the wizard reads them itself — otherwise every call behind a company proxy times out and the token check reports "could not reach the API", which reads as a bad token. doctor prints the one it can see.

The file it writes

.env, at mode 0600, in the app the wizard has written. Its contents are the app's own two variables — VITE_APP_NAME and VITE_APP_LOGO, which belong to the deployment rather than to any module — followed by the union of the selected modules' declared variables, first declaration winning.

Each value is resolved in one order: a value a step already settled (the workspace, brand and auth steps), then the Chatfuel token, then the manifest's default, then empty. A variable that is declared optional and resolves to nothing is written as a commented # NAME= line, so the file documents it without setting it.

.env.example sits beside it. That one is not generated: it travels with the app template and is copied whole, which is why it carries a paragraph of reasoning above every name instead of a value.

The auth module also declares SUPABASE_PROJECT_REF, which the wizard fills in whenever it knows the ref. Nothing reads it at runtime and no deploy pushes it — it is bookkeeping, so you can find the project the app belongs to without opening the URL.

A set-but-empty variable reads as configured everywhere downstream, which is why the wizard writes # NAME= rather than NAME= and why the deploy script skips both. Filling one of those in with an empty value is how a deployment ends up half-gated.

npm start loads a .env sitting next to the app, and real environment variables win over it — so the file the wizard wrote keeps working after a build, and a platform that sets real variables is never overridden by it.

What --embed appends instead of overwriting

An embed lands in a project you already have, which may already have a .env. So the step appends only the keys that file does not define, under a # Added by chatfuel-wizard comment, and never edits a line that is already there.

CaseWhat happens
The key is absentAppended, and reported as added.
The key exists with a different valueLeft untouched, and reported: .env already defines NAME with a different value.
The key exists as a # NAME= placeholder the wizard wrote beforeSkipped, so a re-run does not append it twice.
The file did not existCreated, and only then set to mode 0600 — an existing file's permissions are the host's business.

That tree, those .env keys, a .gitignore line, the skills and the agent's handoff files are the whole footprint. No vite.config, no tsconfig and no CSS of yours is edited — the wiring is the agent's job, guided by the playbooks in the installed skills. The one exception is the dependency install, which you confirm and your own package manager performs.

The guard that refuses to persist a token

Before either mode writes anything to .env, the wizard checks that .gitignore has a line that ignores it. Without one, it asks. Say no and it writes no environment file at all — the app is still scaffolded, and the wizard prints the command that starts it with the token passed on the command line instead.

Under --yes the line is appended without asking — there is nobody there to ask, and the alternative is an unattended run that produces an app with no token in it.

One wrinkle in a packaged install: npm reads a nested .gitignore as ignore rules for its own directory, so the template's copy would drop files from the published tarball. It travels as _gitignore and the scaffold step renames it back — before the guard runs, which is what keeps the guard from failing on a file that is there under another name.

On this page