Start from any project that has a pyproject.toml.
uv tool install --with 'pgpkg[diff]' pgpkg# pyproject.toml
[tool.pgpkg]
project_name = "myext"
# prefix defaults to project_name; override if you need a different file prefix
# prefix = "myext"Create sql/ and write files in the order they should load:
sql/
010_schema.sql
020_tables.sql
030_functions.sql
pre/
001_roles.sql # runs BEFORE every migration (bootstrap or step)
post/
999_grants.sql # runs AFTER every migration
sql/ always represents the current, unreleased state of the database.
pgpkg stageversion 0.1.0This writes migrations/myext--0.1.0.sql. Never edit that file by hand.
pgpkg stageversion 0.2.0
pgpkg makemigration --from 0.1.0 --to 0.2.0This spins up two temporary postgres databases (via results.temporary_local_db),
loads the two staged base files into them, and writes the diff to
migrations/myext--0.1.0--0.2.0.sql.
Review the diff. Edit freely; pgpkg verify will round-trip-check it later.
pgpkg migrate -h localhost -d mydb -U myuser --to 0.2.0Standard libpq environment variables (PGHOST, PGPORT, PGDATABASE,
PGUSER, PGPASSWORD) are honored. You can also pass --dsn 'postgresql://...'.
pgpkg verifyFor every incremental (a -> b) where a and b both have staged base files,
this checks that loading base(a) + a→b produces the same schema as
loading base(b) directly.
pgpkg wheel --output-dir ../myext-migrator
cd ../myext-migrator && uv build --out-dir distThe resulting wheel ships a <project>-migrator migrate console script that
bakes every staged artifact and does not need the source tree at runtime.
See Wrapping into a wheel.