# scribase migrate

Sends a set of migrations to the control-plane API for a specific environment.
Without `--apply` the server lints and plans only — run it that way first to
catch issues before they touch data. With `--apply` the lint must pass before
the migrations execute.

## Usage

```sh
# From a migrations directory (recommended)
scribase migrate <org> <project> <env> --dir ./migrations [--apply]

# From a pre-built migrations JSON file
scribase migrate <org> <project> <env> <migrations.json> [--apply]
```

## Migrations directory format

Scribase discovers `.sql` files in the directory. Two naming shapes are supported:

```
migrations/
├── 001_init.sql            # up-only migration
├── 002_add_users.up.sql    # up migration
├── 002_add_users.down.sql  # paired down migration (optional)
├── 003_indexes.sql
```

Files are ordered by their numeric prefix. The version is the digits before the
first `_`; the name is everything after. Requirements:

- The version prefix must be positive digits.
- The name must not be empty.
- No two files may share the same version.
- A `.down.sql` file must have a matching `.up.sql`.
- Files must not be empty.

## Migrations JSON format

The JSON file must contain an array. Each element:

```json
{
  "version": "1",
  "name": "init",
  "up": "CREATE TABLE ...",
  "down": "DROP TABLE ..."
}
```

`"down"` is optional.

## Options

| Flag | Description |
|---|---|
| `--dir <path>` | Load migrations from a directory of `.sql` files |
| `--apply` | Execute after lint passes (default: lint only) |

## Example

```sh
# Lint first — review the plan before applying
scribase migrate acme store production --dir ./migrations

# Apply after review
scribase migrate acme store production --dir ./migrations --apply
```

## Notes

- Migrations are sent to `POST /v1/organizations/{org}/projects/{project}/environments/{env}/migrations`.
- The server returns a lint report. Review findings before running with `--apply`.
- The migration runner is idempotent by version. Re-sending an already-applied version is a no-op.
- `--apply` is `false` by default — this is intentional. Always review the plan on the first run.
- To capture changes made directly on a database back into this directory, use [`scribase db pull`](https://docs.scribase.com/docs/cli/db-pull.md).
