# Run it in CI, or without a terminal

> --yes answers every question the wizard asks except two, which have to be in the environment — and it refuses two steps outright.

Page: https://sdk.chatfuel.com/docs/guides/non-interactive
Markdown: https://sdk.chatfuel.com/docs/guides/non-interactive.md

Every question the wizard asks has a non-interactive answer, and `--yes` takes it. Two answers are
the exception, because they are credentials and a command line is not the place for them: they
come from the environment or the run stops.

Stopping is the design. The prompt library exits the process on end-of-input, so a scripted run
that fell through to a question nobody could answer would report success and leave nothing behind.
A wizard that says `CHATFUEL_TOKEN is not set` and exits 1 is the version you can put in a
pipeline.

<Steps>
  <Step>
    ### Ask the machine what it can see [#ask-the-machine-what-it-can-see]

    ```bash
    npx @chatfuel/wizard doctor
    ```

    One row each: Node against the floor, the outbound proxy it will use, which coding agents are on
    `PATH`, whether the bundled content tree is complete, and one line per module skill. A missing
    agent is a warning; anything else fails and the command exits 1.

    Run it as the first job of the pipeline. It asks nothing and reaches nothing, so a red row here is
    a machine problem rather than a credentials problem, and you find out before spending a token
    check on it.
  </Step>

  <Step>
    ### Put the two credentials in the environment [#put-the-two-credentials-in-the-environment]

    | Name                    | What needs it                                                                                                         |
    | ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
    | `CHATFUEL_TOKEN`        | Always. There is no flag for it. Generate one at [the token page](https://panel.chatfuel.com/integration/auth/token). |
    | `SUPABASE_ACCESS_TOKEN` | Only with the `auth` module, and only if you are not passing `--supabase-token`.                                      |

    The token is used on the first attempt in place of the prompt, and then checked against the API.
    Under `--yes` there is no second attempt: a token that is missing, or one the API rejects, ends
    the run with a sentence naming which of the two happened.

    `ADMIN_PASSWORD` is read the same way if you install the `admin` module, but it is not part of
    this contract — a run that finds neither the flag nor the variable generates a strong password,
    writes it to `.env` and prints it once.
  </Step>

  <Step>
    ### Answer the rest with flags [#answer-the-rest-with-flags]

    `--yes` alone gives you a standalone app in `./chatfuel-app` with every ready module except the
    opt-in ones, skills in the project, and the Chatfuel workspace picked for you. The flags that are
    worth setting anyway:

    | Flag                    | Why in CI                                                                                                                                                                          |
    | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `--dir <path>`          | The default is `./chatfuel-app` relative to where you started. A directory that exists and is not empty is refused outright.                                                       |
    | `--modules <ids>`       | `--yes` skips opt-in modules, so `auth` and `admin` arrive only if you name them. An unknown id ends the run and lists the ready ones.                                             |
    | `--workspace <id>`      | Taken silently when the account owns exactly one. With several and the `auth` module, `--yes` **refuses** — which workspace pays is not a question to answer on somebody's behalf. |
    | `--agent <id>`          | With both CLIs on `PATH`, `--yes` takes the first one it detected instead of asking. Name the one whose skills layout you want.                                                    |
    | `--app-name` / `--logo` | The name otherwise falls back to the workspace's title; the mark otherwise stays the shipped one, because `--yes` never asks for a logo.                                           |

    `--embed` is the only thing that chooses embed mode — `--yes` on its own stays standalone. The
    full table, including what each flag falls back to, is [the CLI reference](/docs/reference/cli).

    Some things `--yes` does without asking, worth knowing before you point it at a machine you care
    about: it adds `.env` to `.gitignore`, replaces an existing skill directory, installs no coding
    agent when none is present, and starts no dev server at the end.
  </Step>

  <Step>
    ### Name the Supabase project up front [#name-the-supabase-project-up-front]

    The `auth` module is the one module with a second system behind it, and under `--yes` it needs to
    be told which project — a token on its own does not say. There are exactly two accepted shapes:

    <Tabs items="['Access token', 'Manual']">
      <Tab value="Access token">
        `SUPABASE_ACCESS_TOKEN` (or `--supabase-token`) **plus** one of:

        ```bash
        --supabase-project <ref>     # a project that already exists
        --supabase-create <name>     # make one, or reuse the one already called that
        ```

        `--supabase-create` reusing by name is what keeps a repeated pipeline from spending the account's
        other free project on a duplicate. Two projects with that name is an error naming both refs rather
        than a guess.

        Add `--supabase-org <slug>` when the token sees more than one organization — under `--yes` that is
        otherwise a refusal that lists the slugs. `--supabase-region` defaults to the recommended one.
      </Tab>

      <Tab value="Manual">
        ```bash
        --supabase-url https://<ref>.supabase.co --supabase-anon-key <key>
        ```

        Both, together. This path makes no Supabase API call at all: the values go into `.env`, the SQL is
        copied into the app, and applying it is yours.
      </Tab>
    </Tabs>

    Neither shape present and the run stops before the scaffold writes anything, with a hint naming
    every flag that would have worked. A `--yes` run also never creates a project it was not explicitly told to create — that
    is a second, deliberate backstop behind the same rule.
  </Step>

  <Step>
    ### Get the calls out of the network [#get-the-calls-out-of-the-network]

    Node's own `fetch` ignores `HTTP_PROXY` and `HTTPS_PROXY` unless the process was started with a
    flag nobody types, so the wizard reads them itself — `https_proxy`, `HTTPS_PROXY`, `http_proxy`,
    `HTTP_PROXY`, `all_proxy`, `ALL_PROXY`, honouring `NO_PROXY`, with loopback always exempt.

    ```bash
    export HTTPS_PROXY=http://proxy.example:8080
    ```

    What has to be reachable, and when:

    | Host                 | For                                    |
    | -------------------- | -------------------------------------- |
    | `panel.chatfuel.com` | Always.                                |
    | `registry.npmjs.org` | Installing anything.                   |
    | `api.supabase.com`   | The `auth` module's access-token path. |
    | `api.vercel.com`     | Deploying.                             |
    | `api.github.com`     | Pushing to GitHub.                     |

    `doctor` prints the proxy it resolved on its own row, which is the cheapest way to find out that
    the variable is spelled differently than you think.
  </Step>

  <Step>
    ### Rehearse with `--dry-run` [#rehearse-with---dry-run]

    `--dry-run` stops account assets, not files. The app is still written to disk and its dependencies
    still installed; what it holds back are the calls that change something on an account — the
    Chatfuel trial checkout, the Supabase project creation, the database migrations and the auth-config
    patches. Each is printed as the call it would have made. A project it would have created does not
    exist, so there are no keys to read and `.env` carries empty Supabase values.

    So a dry run tells you your flags parse, your tokens work, and your directory is writable, for the
    price of a scaffold you delete afterwards.

    <Callout type="warn">
      One Chatfuel write has no `--dry-run` branch. If the token's account owns **no workspace at
      all**, the workspace step creates one before anything else can continue — under `--dry-run` as
      well. On an account that already has a workspace, nothing is created.
    </Callout>
  </Step>

  <Step>
    ### Run it, and check what came out [#run-it-and-check-what-came-out]

    ```bash
    CHATFUEL_TOKEN="$CHATFUEL_TOKEN" \
    SUPABASE_ACCESS_TOKEN="$SUPABASE_ACCESS_TOKEN" \
    npx @chatfuel/wizard \
      --yes \
      --dir ./chatfuel-app \
      --modules auth,livechat,contacts,deals \
      --workspace 8f3c1d2e-4a5b-6c7d-8e9f-0a1b2c3d4e5f \
      --agent claude \
      --app-name "Acme Concierge" \
      --logo ./brand/acme.svg \
      --supabase-create acme-concierge \
      --app-url https://app.acme.com
    ```

    A failed run exits 1 with the wizard's own sentence and its hint, so the pipeline step goes red on
    its own. A successful one leaves an app with its dependencies installed:

    ```bash
    cd chatfuel-app
    npm run check
    ```

    `tsc` passing over the whole app is the check that means the registry, the modules and the
    vendored trees all agree. Then read `.env`: every variable the run resolved is in it, and it is the
    file the deployment's configuration is pushed from.

    Two things will not be there, on purpose. **No deployment**, and **no GitHub repository**: both
    steps are interactive-only and skipped under `--yes`, without a TTY, and under `--dry-run`. A
    deployment is a public URL with your Chatfuel token behind it, and a repository under your account
    holds the source of an app wired to your bot; neither is something a flag should be able to cause.
    Both are ordinary commands afterwards — `npm run deploy` and `gh repo create --source . --push`.
  </Step>
</Steps>

Next: [deploy](/docs/deploy) for the step `--yes` would not take, or
[the CLI reference](/docs/reference/cli) for every flag and its fallback.
