Run an Atlas project on ptah-compat
Point the Atlas-compatible binary at the atlas.hcl and migration directory you already have, and check that nothing moved.
You have an atlas.hcl, a migration directory whose history is applied in real
databases, and CI steps that call Atlas verbs. One thing changes: which binary
runs them. The project file stays, the directory stays, atlas.sum stays, and
the commands stay. At the end you are on ptah-compat, which is a place to
stop rather than a staging area to escape from.
The two halves of the move are not equally provable, and the page treats them
differently. The community-edition surface is what ptah-compat targets, and
what it covers is measured rather than asserted: the
feature matrix answers it per capability, and
every command below runs in this repository’s continuous integration on Linux,
macOS and Windows. Capabilities Atlas gates behind a paid tier are answered by
different machinery, described rather than executed, in
What the gated capabilities become.
What you need
Section titled “What you need”ptah-compatandptahon yourPATH. Install Ptah ships both.- A terminal and about ten minutes.
No database server, Docker, or Go toolchain is required.
Run the commands you already run
Section titled “Run the commands you already run”Build a project with history
Section titled “Build a project with history”The fixture is an atlas.hcl with one env and a directory holding two
migrations, which is the smallest shape that can prove anything. Yours is
larger; nothing below cares how much larger.
mkdir -p ptah-from-atlas/migrationscd ptah-from-atlascat > atlas.hcl <<'HCL'env "local" { url = "sqlite://app.db" migration { dir = "file://migrations" }}HCLcat > migrations/20240101000000_create_users.sql <<'SQL'CREATE TABLE users ( id INTEGER PRIMARY KEY, email TEXT NOT NULL);SQLcat > migrations/20240102000000_add_email_index.sql <<'SQL'CREATE UNIQUE INDEX users_email_idx ON users (email);SQLNew-Item -ItemType Directory ptah-from-atlas/migrations | Out-NullSet-Location ptah-from-atlas@'env "local" { url = "sqlite://app.db" migration { dir = "file://migrations" }}'@ | Set-Content atlas.hcl@'CREATE TABLE users ( id INTEGER PRIMARY KEY, email TEXT NOT NULL);'@ | Set-Content migrations/20240101000000_create_users.sql@'CREATE UNIQUE INDEX users_email_idx ON users (email);'@ | Set-Content migrations/20240102000000_add_email_index.sqlYour own directory already carries atlas.sum. This one does not yet, so seal
it the way the directory was sealed in the first place:
ptah-compat migrate hash --env localRead the directory back
Section titled “Read the directory back”ptah-compat migrate validate --env localA sealed directory validates silently and exits zero. That is Atlas’s contract for this verb and it is kept here, so a pipeline step that asserts on empty output keeps passing.
ptah-compat migrate status --env localExpected output on standard output:
Migration Status: PENDING -- Current Version: No migration applied yet -- Next Version: 20240101000000 -- Executed Files: 0 -- Pending Files: 2No flag named the database. --env local selected the env block, and the
url and migration { dir } in atlas.hcl answered the rest.
ptah-compat migrate apply --env localExpected output on standard output:
Migrating to version 20240102000000 from 2 pending migrations.Migration complete. Current version: 20240102000000ptah-compat migrate status --env localExpected output on standard output:
Migration Status: OK -- Current Version: 20240102000000 -- Next Version: Already at latest version -- Executed Files: 2 -- Pending Files: 0The revisions landed in atlas_schema_revisions, the table Atlas writes, in
the layout Atlas writes it. Nothing converted the history on the way in.
The integrity gate is the same gate
Section titled “The integrity gate is the same gate”Editing an applied migration is the mistake the checksum file exists to catch. Make it:
cat > migrations/20240102000000_add_email_index.sql <<'SQL'CREATE UNIQUE INDEX users_email_idx ON users (email, id);SQL@'CREATE UNIQUE INDEX users_email_idx ON users (email, id);'@ | Set-Content migrations/20240102000000_add_email_index.sqlptah-compat migrate validate --env localExpected output on standard output:
You have a checksum error in your migration directory.
L3: 20240102000000_add_email_index.sql was edited
Please check your migration files and run 'atlas migrate hash' to re-hash the contentsExpected output on standard error:
Error: checksum mismatchThe remedy names the atlas binary because this is the Atlas-compatible
wording and Ptah keeps it as it is. A CI job that greps this output keeps
working, which is the point of matching the wording rather than improving it.
Put the file back:
cat > migrations/20240102000000_add_email_index.sql <<'SQL'CREATE UNIQUE INDEX users_email_idx ON users (email);SQL@'CREATE UNIQUE INDEX users_email_idx ON users (email);'@ | Set-Content migrations/20240102000000_add_email_index.sqlLint the same directory
Section titled “Lint the same directory”ptah-compat migrate lint --env local --dev-url "sqlite://dev.db" --latest 1Expected output includes, on standard output:
Analyzing changes from version 20240101000000 to 20240102000000 (1 migration in total): -- analyzing version 20240102000000The finding it prints for this fixture is a unique index built over rows that already exist. Ptah’s rule catalog is its own and is larger than the Atlas-compatible surface needs; migration lint rules enumerates it.
What the gated capabilities become
Section titled “What the gated capabilities become”Atlas keeps part of its product behind a paid tier, and a pipeline that depends on one of those parts is the reason this move needs thinking about rather than scheduling. The answer is usually better than expected: the capability exists here, behind different machinery, and behind no tier. What it is not is the same machinery, so each one is a change to your pipeline rather than a no-op.
| What your pipeline uses | What runs here |
|---|---|
| A hosted registry holding migration directories and schemas | An OCI registry you already run. ptah oci logs in, inspects, fetches, copies and verifies artifacts and the metadata attached to them, and an oci-layout:// directory stands in where there is no registry to reach. |
| A hosted lint report | ptah migrations lint --format writes sarif, gitlab, github-actions or json, and --attach puts the canonical JSON report on the migration artifact so it travels with what it describes. |
| Registry-mediated plan approval | ptah-compat schema plan computes the plan and saves a .plan.hcl locally; ptah schema approve signs one and ptah schema verify-approval checks the signature against the signers you allow. There is no identity service to run, and plan and approve walks it. |
| Schema and migration testing | ptah-compat schema test and ptah-compat migrate test read .test.hcl, and ptah schema test is the native path. |
ptah-compat schema plan has no working approve, push, pull, list or
rm: those sub-verbs address a remote registry and answer that they are not
implemented. The local plan file plus the native signature is the whole
replacement, and it is a different shape rather than a smaller one.
Atlas feature matrix is the row-by-row reference for everything above, and OCI registry documents the registry side in full.
Ask what native Ptah would take over
Section titled “Ask what native Ptah would take over”Nothing so far required native Ptah, and nothing below changes the project.
ptah project adopt --check reads the same atlas.hcl and reports what a
native Ptah would make of every construct in it.
ptah project adopt --checkExpected output includes, on standard output:
exact (2): database url migration dirAdd --preflight and the same command reads the revision history the database
holds, which is the half a verdict about a file cannot cover:
ptah project adopt --check --preflightExpected output includes, on standard output:
✓ every recorded revision finished ✓ every recorded revision names a migration this directory contains ✓ no recorded checksum contradicts the migration it namesThe non-zero status is the useful part. The file is native-ready and the
database still holds its history in the Atlas-compatible layout, so one
decision remains before a native writer could take over — and you do not have
to make it. Staying on ptah-compat is a supported end state.
Migrate from Atlas is the page for readers who want to
go further, and it covers that decision in reversible stages.
Clean up
Section titled “Clean up”cd ..rm -rf ptah-from-atlasSet-Location ..Remove-Item -Recurse -Force ptah-from-atlasWhere this leaves you
Section titled “Where this leaves you”Your commands, your project file and your history are where they were, and the
binary in front of them is ptah-compat. What that binary covers is measured
rather than asserted: Atlas compatibility is the
summary, feature matrix the per-capability
table, and retained divergences the list
of places Ptah deliberately does not reproduce a behavior, each with the reason.
ptah-compat keeps every capability Ptah models, which means it accepts some
input the community binary refuses. Strict CE mode
is the switch that narrows it to a community-edition-only policy for
conformance runs, and it is worth knowing about before you rely on the move.
License boundary states how the compatibility
work is done and what it does not touch.