# Run a blueprint from the command line

Validate, plan, apply and export a blueprint with npx, set the API key safely, and check for drift in CI.

The command line interface (CLI) is a program you run by typing a command in a terminal. A **terminal** is the window where you type commands: **Terminal** on a Mac, **PowerShell** on Windows. The BuildBase CLI is part of the @buildbase/sdk package, and it runs the same validate, plan and apply as the [console](/blueprints/overview#your-first-blueprint-in-the-console).

```bash
npx buildbase blueprint validate   # check the file, change nothing
npx buildbase blueprint plan       # list what would change
npx buildbase blueprint apply      # make the changes, after you type yes
```

> **Note:**

- [Node.js](https://nodejs.org) 18 or later. Type `node --version` in a terminal to see yours.
- An API key with the owner or admin role. [Before you start](/blueprints/overview#before-you-start) shows how to make one.
- A blueprint file. In the console, open **Setup**, press **Set up from one file**, then **Download current setup**. Or run `export` below.



The `blueprint` commands ship in `@buildbase/sdk` 1.0.0. If a command answers `Unknown command: blueprint`, you ran an earlier version.

## Install nothing beyond Node

Node.js comes with `npx`, which downloads a package and runs it. You do not need to install anything else.

- **In a project that already has the SDK installed**, run `npx buildbase blueprint ...`. It uses the SDK in that project.
- **Anywhere else**, run `npx @buildbase/sdk blueprint ...`. The first time, `npx` asks to download the package: type `y` and press Enter.

The examples on this page use `npx buildbase`. Replace it with `npx @buildbase/sdk` when the SDK is not installed in your project.

## Set the two variables safely

The CLI reads two **environment variables**: named values that your terminal passes to every program it starts. They stay in that terminal window only, and are gone when you close it.

| Variable               | What it holds                                                                                                                                                                                           |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BUILDBASE_SERVER_URL` | Your BuildBase server. [https://api.console.buildbase.app](https://api.console.buildbase.app) on BuildBase's cloud, or your own server when self-hosted |
| `BUILDBASE_API_TOKEN`  | Your API key: the organization ID, a colon and the secret                                                                                                                                               |

The CLI never takes the API key as an option, so it does not end up in your shell history or in a log. Type it with a command that hides what you type.

On a Mac or Linux:

```bash
export BUILDBASE_SERVER_URL=https://api.console.buildbase.app
read -rs BUILDBASE_API_TOKEN && export BUILDBASE_API_TOKEN
```

On Windows, in PowerShell 7.1 or later:

```powershell
$env:BUILDBASE_SERVER_URL = "https://api.console.buildbase.app"
$env:BUILDBASE_API_TOKEN = Read-Host -MaskInput "API key"
```

After `read -rs` or `Read-Host`, paste the key and press Enter. Nothing shows while you paste, on purpose.

`--server-url` sets the server for one command instead of `BUILDBASE_SERVER_URL`. If neither is set, the CLI also reads `NEXT_PUBLIC_BUILDBASE_SERVER_URL`, the variable a Next.js app with the SDK already has.

### Values for `${env:NAME}`

A blueprint writes each secret as `${env:NAME}` (see [secrets](/blueprints/file-format#secrets-and-env-name)). The CLI fills each one from an environment variable of that name, or from a file named with `--env-file`:

```bash title=".env.staging"
APP_URL=https://staging.acme.example
STRIPE_SECRET_KEY=sk_test_your_key_here
```

```bash
npx buildbase blueprint plan --env-file .env.staging
```

- A variable already set in the terminal wins over the same name in the file.
- Only the names the blueprint uses are sent to BuildBase. The rest of your environment stays on your computer.
- `--env-file` does not supply `BUILDBASE_API_TOKEN`. Set that one in the terminal.
- Keep files such as `.env.staging` out of Git: add them to `.gitignore`.
- Check the file name. On Node.js 20 and 22, Node reads `--env-file` too, so a file that does not exist stops Node itself with `node: .env.staging: not found` before the CLI starts.

## Commands

`validate`, `plan` and `apply` read `buildbase.blueprint.json` in the folder you run them from. To use another file, name it after the command: `npx buildbase blueprint plan staging.blueprint.json`.

| Command           | What it does                                                                                     |
| ----------------- | ------------------------------------------------------------------------------------------------ |
| `validate [file]` | Checks the file: its format, its fields, references between entries and secrets. Changes nothing |
| `plan [file]`     | Compares the file with your organization and prints what would change. Changes nothing           |
| `apply [file]`    | Plans, shows the plan, asks you to type `yes`, applies, then prints the result and a recheck     |
| `export`          | Writes your organization's current setup as a blueprint                                          |
| `schema`          | Writes the JSON Schema, the description of every field, for code editors and AI agents           |
| `mcp`             | Runs the commands as a server for AI agents. See [AI agents](/blueprints/ai-agents)              |

### validate

```bash
npx buildbase blueprint validate
```

It lists each problem with the place in the file, then the `${env:NAME}` values that are not set yet, after `Not set (needed to apply):`. A valid file ends with `buildbase: buildbase.blueprint.json is valid.`, and a file with problems ends with `is not valid`.

### plan

```bash
npx buildbase blueprint plan --env-file .env.staging
```

It prints one line for each thing that would change, then a summary. Add `--verbose` to also list what is unchanged. [How to read a plan](/blueprints/file-format#reading-a-plan) explains every symbol.

### apply

```bash
npx buildbase blueprint apply --env-file .env.staging
```

1. The CLI makes a plan and prints it.
2. It asks `Apply these changes to the organization? Type "yes" to go ahead:`. Type `yes` and press Enter. Any other answer stops it, and nothing changes.
3. It applies the plan you saw, by sending that plan's hash. If your organization changed since that plan, BuildBase refuses, and you plan again.
4. It prints each step and a recheck: the plan made again, which shows anything still different.

When there is nothing to change, it says the organization already matches the file, and stops. If a step fails, it says which one, and that the steps before it were applied.

### export

```bash
npx buildbase blueprint export --out buildbase.blueprint.json
```

Without `--out`, it prints the blueprint in the terminal. With `--out`, it writes the file. Either way, it lists the secrets to set before you plan the file. It does not replace a file that exists unless you add `--force`.

### schema

```bash
npx buildbase blueprint schema --out blueprint.schema.json
```

## Options

| Option               | Used by                     | What it does                                                                                                                                                      |
| -------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--env-file <file>`  | `validate`, `plan`, `apply` | A file of `NAME=value` lines for `${env:NAME}`. A variable set in the terminal wins                                                                               |
| `--prune`            | `plan`, `apply`             | Also delete what this blueprint created and the file no longer lists, for the kinds in `policy.prune`                                                             |
| `--yes`              | `apply`                     | Apply without asking. Needed where nobody can type, such as CI: without a terminal and without `--yes`, apply refuses                                             |
| `--outputs <file>`   | `apply`                     | Where shown-once values go. The default is `.buildbase/blueprint-outputs.json`                                                                                    |
| `--out <file>`       | `export`, `schema`          | Write to this file instead of the terminal                                                                                                                        |
| `--force`            | `export`, `schema`          | Replace the `--out` file if it exists                                                                                                                             |
| `--json`             | `validate`, `plan`, `apply` | Print the server's JSON reply, as one JSON document, instead of text. The text for people goes to the error output. Shown-once values are replaced by their names |
| `--server-url <url>` | every command except `mcp`  | Use this server instead of `BUILDBASE_SERVER_URL`. It must start with `http://` or `https://`                                                                     |
| `--verbose`          | `plan`, `apply`             | Also list what is unchanged                                                                                                                                       |
| `--help`             | every command               | Print the commands and options                                                                                                                                    |

An option that takes a value works as `--out file` or `--out=file`.

## Exit codes

When a command ends, it returns a number, its **exit code**. Scripts and CI read it to decide what to do next.

| Code | Meaning                                                                                                                                                                         |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`  | Done. `validate`: the file is valid. `plan`: nothing would change. `apply`: applied, or nothing to apply                                                                        |
| `1`  | An error: an invalid file, a refused key, a server error, a failed or refused apply, an apply you did not confirm, an `--out` file that exists, or a mistyped command or option |
| `2`  | `plan` only: the file and the organization differ                                                                                                                               |

A version of the SDK from before the `blueprint` commands answers `Unknown command` with exit code `2`. So a script that reads `2` as "changes found" should run `validate` first: an SDK without the commands fails there.

## Where shown-once values go

An apply that creates a webhook, an API key, an auth client, a text message webhook or web push keys gets values that BuildBase shows only once. The CLI never prints them, even with `--json`: the result says `(shown only once, so it is not printed here)` for each one. It adds them to `.buildbase/blueprint-outputs.json` (or the `--outputs` file), under the address of the thing that made them, and prints the file name.

- On a Mac or Linux, the file is created so that only your user account can read it.
- Before it changes anything, apply checks the file. If a file with that name exists and is not an outputs file, apply stops, so it never writes over another file.
- Move the values to your password manager or secret store, then delete the file.
- Add `.buildbase/` to your `.gitignore`, so the file is never committed.

## Check for drift in CI

**Drift** means the organization no longer matches the file, because someone changed a setting in the console. CI (continuous integration) is a service that runs commands for you, on a schedule or when code changes. This GitHub Actions workflow plans every weekday morning and fails when the organization has drifted from the file in your repository:

```yaml title=".github/workflows/blueprint-drift.yml"
name: Blueprint drift
on:
  schedule:
    - cron: '0 7 * * 1-5'
  workflow_dispatch:

jobs:
  plan:
    runs-on: ubuntu-latest
    env:
      BUILDBASE_SERVER_URL: https://api.console.buildbase.app
      BUILDBASE_API_TOKEN: ${{ secrets.BUILDBASE_API_TOKEN }}
      APP_URL: ${{ vars.APP_URL }}
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Validate the file
        run: npx --yes @buildbase/sdk blueprint validate
      - name: Plan
        run: |
          code=0
          npx --yes @buildbase/sdk blueprint plan || code=$?
          if [ "$code" = 2 ]; then
            echo "::error::The organization no longer matches buildbase.blueprint.json"
          fi
          exit $code
```

1. In your repository on GitHub, open **Settings**, then **Secrets and variables**, then **Actions**.
2. Add a secret named `BUILDBASE_API_TOKEN` with your API key.
3. Add a variable for each `${env:NAME}` the file uses outside a secret field, such as `APP_URL`. Secrets in the file are optional for a drift check: a secret that is not set is not compared.
4. Commit the workflow file next to `buildbase.blueprint.json`.

`--yes` after `npx` lets it download the package without asking. To apply from CI, for example after a change is merged, run `npx --yes @buildbase/sdk blueprint apply --yes`, and store the shown-once values it writes before the job ends.

## Next steps

- [File format](/blueprints/file-format) - what each section of the file holds
- [AI agents](/blueprints/ai-agents) - run these commands from an AI coding agent
- [Troubleshooting](/blueprints/troubleshooting) - what each message means and what to do
