A generic file migration tool that applies ordered transformations to a project directory. Think database migrations, but for files and project setup. Migrations can be written in any language (bash, TypeScript, Python, etc.) using shebangs.
Download the pre-built binary for your platform from GitHub Releases, then move it to a directory in your PATH:
# Example for macOS (Apple Silicon)
curl -L https://github.com/glideapps/migrate/releases/latest/download/migrate-aarch64-apple-darwin -o migrate
chmod +x migrate
sudo mv migrate /usr/local/bin/If you have Rust installed, cargo-binstall downloads pre-built binaries:
# Install cargo-binstall first (if you don't have it)
cargo install cargo-binstall
# Then install migrate
cargo binstall migrateRequires Rust:
cargo install migratecargo install --git https://github.com/glideapps/migrate# Check what migrations exist and their status
migrate status
# Apply all pending migrations
migrate up
# Preview what would happen without making changes
migrate up --dry-runCreate a new migration with migrate create:
migrate create add-prettier # Bash script (default)
migrate create setup-config --template ts # TypeScript
migrate create init-db --template python # PythonThis generates a timestamped file like 1fb2g-add-prettier.sh in your migrations/ directory. The 5-character prefix ensures migrations run in chronological order.
Available templates: bash, ts, python, node, ruby
Migrations are executable files that receive context via environment variables:
| Variable | Description |
|---|---|
MIGRATE_PROJECT_ROOT |
Absolute path to project root |
MIGRATE_MIGRATIONS_DIR |
Where migration files live |
MIGRATE_ID |
Current migration ID (e.g., 1fb2g-add-prettier) |
MIGRATE_DRY_RUN |
true if running in preview mode |
Bash example:
#!/usr/bin/env bash
set -euo pipefail
# Description: Add TypeScript configuration
cd "$MIGRATE_PROJECT_ROOT"
cat > tsconfig.json << 'EOF'
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"strict": true
}
}
EOFTypeScript example:
#!/usr/bin/env -S npx tsx
// Description: Add configuration file
import * as fs from 'fs/promises';
import * as path from 'path';
const projectRoot = process.env.MIGRATE_PROJECT_ROOT!;
await fs.writeFile(
path.join(projectRoot, 'config.json'),
JSON.stringify({ version: 1 }, null, 2)
);Run migrate up to apply all pending migrations in order. Each successful migration is recorded in .history, so it won't run again.
migrate up # Apply all pending
migrate up --dry-run # Preview without applyingIf a migration fails, execution stops immediately. Fix the issue and re-run migrate up—already-applied migrations are skipped.
Use migrate status to see what's been applied and what's pending:
Version: 1fb2g → 1fc3h (2 pending)
Applied (3):
✓ 1fa1f-init-project
✓ 1fa2g-add-typescript
✓ 1fb2g-setup-eslint
Pending (2):
• 1fc2h-add-prettier
• 1fc3h-configure-ci
Over time, your migrations/ directory accumulates files. Once migrations have been applied everywhere (all environments, all team members), you can baseline to clean up.
Baselining marks a version as the "starting point"—migrations at or before that version are considered complete and can be deleted.
# Mark version 1fb2g as baseline and delete old migration files
migrate baseline 1fb2g
# Preview what would be deleted without making changes
migrate baseline 1fb2g --dry-run
# Create baseline but keep the files (just update .baseline)
migrate baseline 1fb2g --keepYou can also baseline immediately after applying migrations:
migrate up --baseline # Apply and baseline at final version
migrate up --baseline --keep # Apply and baseline without deleting filesWhen to baseline:
- All environments have applied the migrations
- All team members have pulled and applied
- You want to reduce clutter in the migrations directory
What baselining does:
- Creates/updates
.baselinefile with the baseline version - Optionally deletes migration files at or before that version
- Future
migrate upskips migrations covered by the baseline
your-project/
├── migrations/
│ ├── .history # Tracks applied migrations (auto-generated)
│ ├── .baseline # Baseline marker (optional, from baselining)
│ ├── 1fc2h-add-prettier.sh
│ └── 1fc3h-configure-ci.ts
└── ...
These options work with all commands:
| Option | Description | Default |
|---|---|---|
-r, --root <path> |
Project root directory | . |
-m, --migrations <path> |
Migrations directory | migrations |
git clone https://github.com/glideapps/migrate
cd migrate
./scripts/setup # Enable git hooks, fetch deps, build, test
cargo build # Build debug binary
cargo nextest run # Run tests
cargo fmt # Format code
cargo clippy # Lint