Database migrations without surprises.

Ptah compares the schema you want with a live database and either writes versioned migrations or applies an approved plan. It also migrates persistent inference state, such as re-embedding a pgvector table. PostgreSQL, MySQL, MariaDB, SQLite and more. Open source, MIT, no toolchain to install.

$ curl -fsSL https://ptah.run/install.sh | sh

v0.3.0 · pre-GA · MITWindows: irm https://ptah.run/install.ps1 | iex

$ ptah schema apply --schema-file schema.sql \
    --db-url sqlite://app.db --dry-run
Planned schema changes:
ALTER TABLE "users" ADD COLUMN "created_at" TEXT;

$ ptah schema apply --schema-file schema.sql \
    --db-url sqlite://app.db --auto-approve
Planned schema changes:
ALTER TABLE "users" ADD COLUMN "created_at" TEXT;
Auto-approval enabled; applying schema changes.
Schema apply completed successfully.

$ ptah schema drift --schema-file schema.sql \
    --db-url sqlite://app.db
No schema drift detected.
$ echo $?
0

Know exactly what your migration will do before it touches the database. The plan is the review surface; drift is the proof.

Three things it does in a typical week.

Real commands, real output. Exit codes are stable across all of them: 0 success, 1 a negative check result, 2 a usage or connection failure.

01 · Gate a pull request

Fail CI when the schema drifted or a migration is unsafe.

$ ptah migrations lint --dir ./migrations \
    --dialect postgres
No lint findings.
$ ptah schema drift \
    --schema-file schema.sql \
    --db-url "$PTAH_DATABASE_URL"
No schema drift detected.

Or uses: stokaro/ptah-action@v1, which posts the plan to the pull request and writes a destructive-change check run.

02 · Seal a migration directory

Refuse a migration file whose bytes changed after review.

$ ptah migrations hash --dir ./migrations
Wrote ./migrations/ptah.sum
2 migration file(s) hashed
$ ptah migrations status \
    --db-url sqlite://app.db \
    --migrations-dir ./migrations
Current Version: 1700000000
Total Migrations: 1
Applied Migrations: 1
Pending Migrations: 0

ptah.sum records a checksum per file; later commands verify it before running anything.

03 · Change an embedding model

Re-embed a pgvector table and keep the old vectors until verified.

ptah inference plan
ptah inference prepare
ptah inference backfill
ptah inference catchup
ptah inference index
ptah inference verify
ptah inference cutover
ptah inference rollback · retire

Ptah builds the new generation beside the active one, calls your OpenAI-compatible embeddings endpoint, verifies, and switches queries over when you say so. It never produces a vector itself.

Works with the schemas you already have.

Every source parses into the same internal schema before planning. --schema-file and --root-dir repeat and mix freely; the merged result is the desired schema. No proprietary format is required.

--schema-file
SQL, YAML, HCL, DBML
--root-dir
Annotated Go structs
--schema-cmd
Any program that emits SQL, HCL or YAML — an ORM exporter
--db-url
A live database, introspected into Go models with ptah introspect
Databases

PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, CockroachDB, YugabyteDB, ClickHouse, Oracle, Spanner. Coverage varies by engine. Support matrix →

Tooling

ptah is the product. ptah-ls gives editor support for Go annotations. GitHub Action, Go packages at go.5x5.cz/ptah.

Coming from Atlas

ptah-compat keeps Atlas-shaped commands while executing Ptah behavior. Independent clean-room implementation, not affiliated with Ariga. Atlas compatibility →