new migration
go tool gpsystem new migration <name>
Run inside a project (the CLI walks up to gpsystem.yaml). It creates a migration file under migrations/, stamped with the current time, with an empty goose skeleton: you write the SQL, and the project's cmd/migrate binary takes care of running it.
Naming
The CLI normalizes the name to snake_case: it lowercases and unifies hyphens, underscores and spaces into underscores. The normalized name must consist of lowercase letter/digit words (no path separators, dots or a leading digit); anything that does not comply is rejected with an error.
go tool gpsystem new migration create_products_and_orders
go tool gpsystem new migration "add index to orders" # -> add_index_to_orders
Timestamp
The command derives a 14-digit YYYYMMDDHHMMSS prefix (goose's timestamp scheme) from the current UTC time and puts it in front of the filename. Because it captures the moment of generation, it is guaranteed to sort after everything already in migrations/, and it never collides across branches. If the directory already has a migration for the exact same second, the command steps forward one second at a time until it finds a free prefix. Generated projects ship with 20200101000000_init.sql and 20200101000100_outbox.sql (a fixed, early timestamp), so your first own migration always sorts after them, at the actual time you created it:
go tool gpsystem new migration create_products_and_orders
# Migration created: migrations/20260720143012_create_products_and_orders.sql
It also works correctly against an older, sequentially-numbered project (00001_init.sql, 00002_outbox.sql): the command only considers 14-digit timestamp prefixes when checking for collisions, leaves the old sequential files untouched, and goose sorts both numerically, in the right order.
What it generates
A single file: migrations/<timestamp>_<name>.sql, with an empty up/down skeleton:
-- +goose Up
-- +goose StatementBegin
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
-- +goose StatementEnd
The global --dry-run (prints the plan, writes nothing) and --force (overwrite existing files) flags work here too, as on every subcommand.
After generation
Write the SQL between the markers (the change into the Up section, its rollback into Down), then apply it:
go run ./cmd/migrate up
The file format, the cmd/migrate commands and the deployment patterns are covered on the Migrations page.