stig

SQLite migrations, snapshots, and codegen. All from one binary.

An open-source command-line tool for SQLite migrations and schema management, written in Rust.

$ cargo install stig

The name

"stig" is Swedish for path, or footpath. The verb form means to step, or to ascend.

Each migrate is a step forward along that path. Each snapshot is a footprint left behind, in case you ever need to find your way back.

What stig does

Four jobs, one binary

Forward-only migrations

Applies pending migrations in lexicographic order, with checksum verification so nobody's local edits get silently skipped.

Filesystem snapshots

Takes a snapshot before every migration, so you can redo back to it and replay forward without touching a backup service.

Drift detection

stig status catches when an applied migration's file has changed underneath you, before it causes a surprise.

Schema-aware codegen

Generates TypeScript types straight from your live schema, so your types never drift from the database that backs them.

Usage

Quickstart

Install with cargo, then run stig init in your project. From there it's a loop: write a migration, apply it, and let stig snapshot as it goes.

developer · stig · 80×24
# bootstrap a new project
$ stig init
✓ project initialized

# create a timestamped migration file
$ stig new create_users
→ opens $EDITOR

# apply all pending migrations, snapshot taken automatically
$ stig migrate
✓ 1 applied

# generate TypeScript types from the live schema
$ stig generate
✓ typescript → lib/database/types.ts

Command reference

Core commands

CommandWhat it does
initBootstraps a new project: config file, migrations directory, backups directory, and the schema_migrations table.
new <description>Creates a timestamped migration file and opens it in $EDITOR.
migrateApplies all pending migrations in order, with automatic snapshots and checksum verification. --dry-run previews without applying.
statusReports applied, pending, and drifted migrations, without making changes.
redo [version]Restores the snapshot from before a version and replays migrations forward from there. Defaults to the most recent.
resetMoves the live database into backups and re-migrates from empty. Destructive; prompts for confirmation.
restore [timestamp]Restores the database from a reset backup. Defaults to the most recent.
generate [target]Runs configured codegen targets against the live schema. Runs all targets if none is named.
backups listLists snapshots and reset backups with sizes and ages.
backups pruneRemoves old backups according to retention policy. Prompts for confirmation.

How it works

Seven scenarios, step by step

Every path stig can take, from the happy path to error recovery. Trail colour marks who's acting: developer, stig, the database, or the filesystem.

Happy path: first migration

Bootstrapping a project and applying your first migration.

DeveloperRealizes schema needs a new table
stigstig init: creates config, migrations dir, snapshots dir
Databaseschema_migrations table created
stigstig new create_users: scaffolds migration file
DeveloperWrites SQL in $EDITOR
stigstig migrate
stigSnapshot taken: pre-VERSION.db
DatabaseCREATE TABLE users (...) executed
stigRecorded in schema_migrations
DeveloperVerifies DB has the new table
Developer
stig
Database
Filesystem

Edit an applied migration, snapshot available

Local testing reveals a mistake. The pre-migration snapshot is still around, so redo recovers it.

DeveloperLocal testing reveals the column type is wrong
DeveloperEdits the migration SQL file directly
stigstig status: compares checksums against schema_migrations
stigDrift detected: snapshot pre-VERSION.db is available
Developerstig redo VERSION
FilesystemRestores pre-VERSION.db over the live database
stigRe-applies the edited migration, then any later ones
DeveloperVerifies the corrected schema
Developer
stig
Database
Filesystem

Edit an applied migration, snapshot pruned

Same mistake as above, but the snapshot's gone (default: only 5 kept). Choose between starting fresh or keeping the old data.

DeveloperLocal testing reveals the column type is wrong
DeveloperEdits the migration SQL file directly
stigstig status: drift detected, but the snapshot has been pruned
DeveloperChooses: start fresh, or keep the old data

Start fresh

  1. Developerstig reset --yes
  2. FilesystemMoves the live database into resets/
  3. stigRe-migrates from empty
  4. DeveloperRe-seeds or re-imports data

Keep old data

  1. Developerstig restore --yes
  2. FilesystemRestores the most recent reset backup
  3. DeveloperContinues testing with the old data
Developer
stig
Database
Filesystem

Migration SQL error

A syntax error or a reference to a table that doesn't exist. Transactional migrations auto-rollback; non-transactional ones auto-restore from snapshot.

DeveloperWrites migration SQL (contains an error)
Developerstig migrate
stigSnapshot taken before applying

Transactional (default)

  1. DatabaseSQLite auto-rolls back the failed transaction, no partial state

Non-transactional

  1. Filesystemstig auto-restores the pre-migration snapshot
stigMigration failed, not recorded in schema_migrations
DeveloperReads the error, fixes the SQL
Developerstig migrate (retry), applies cleanly
Developer
stig
Database
Filesystem

Reset and restore

Test against a clean database without losing existing data. reset backs up the live database, restore brings it back.

DeveloperWants to test against an empty database
Developerstig reset --yes
FilesystemMoves the live database into resets/
stigRe-applies all migrations from empty
DeveloperTests against the fresh schema
Developerstig restore --yes
FilesystemCopies the reset backup back over the live database
DeveloperVerifies the original data is back
Developer
stig
Database
Filesystem

Codegen flow

After migrating, generate TypeScript types from the live schema.

Developerstig migrate: applies pending migrations
Developerstig generate
stigReads the live schema
stigWrites lib/database/types.ts
DeveloperReviews the generated types
DeveloperCommits the types alongside the migrations
Developer
stig

Dry-run / preview flow

Preview what would change before applying, for catching surprises early.

DeveloperWrites migration SQL
Developerstig status: one migration pending
Developerstig migrate --dry-run
stigPlans without executing, no changes made

Looks good

  1. Developerstig migrate, applies for real

Something's off

  1. DeveloperEdits the migration, then retries
Developer
stig

Open source

MIT licensed

Built in the open, for anyone to use

stig is free and open source under the MIT license. Issues, questions, and pull requests are welcome on GitHub.