
Database Migration
- 14.5k installs
- 38.3k repo stars
- Updated July 22, 2026
- wshobson/agents
wshobson/agents is a multi-harness plugin marketplace that ships 92 production-ready agent plugins, 199 domain-expert agents, 162 skills, and 106 commands compiled to five AI coding harnesses (Claude Code, Codex, Cursor,
About
A production-grade agentic plugin marketplace with 92 composable plugins, 199 domain-expert agents, and 162 skills that compile to five AI coding harnesses (Claude Code, Codex, Cursor, OpenCode, Gemini, Copilot). Each plugin isolates its own agents, commands, and skills - install only what you need. Includes orchestrators for multi-agent coordination (full-stack builds, security, ML, incident response) and tiered model selection (Fable 5 for long-horizon work down to Haiku for fast ops).
- 92 production-ready plugins spanning architecture, languages, infra, security, data, ML, docs, and business
- Single Markdown source compiles to five harnesses: Claude Code, Codex, Cursor, OpenCode, Gemini, Copilot
- 199 domain-expert agents + 162 skills + 106 slash commands for autonomous workflow orchestration
Database Migration by the numbers
- 14,536 all-time installs (skills.sh)
- +240 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #60 of 16,659 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
database-migration capabilities & compatibility
- Capabilities
- multi agent orchestration · plugin composition · harness abstraction · tiered model selection
- Platforms
- macOS · Linux · Windows
- IDEs
- vscode · cursor ide · jetbrains · neovim
- Runs
- Runs locally
- Pricing
- Free
npx skills add https://github.com/wshobson/agents --skill database-migrationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 14.5k |
|---|---|
| repo stars | ★ 38.3k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 22, 2026 |
| Repository | wshobson/agents ↗ |
What it does
Build production agentic workflows with composable plugins across architecture, security, data, and DevOps domains - one source compiles idiomatic code for five harnesses.
Who is it for?
Teams building autonomous agentic systems with multi-language, multi-domain coverage; single Markdown source requirement across five harnesses
Skip if: Greenfield prototypes with disposable databases where destructive migrations are acceptable.
When should I use this skill?
Need composable agent plugins for full-stack builds, security reviews, ML workflows, or incident response
What you get
Install a plugin, get idiomatic agents/skills/commands for all five harnesses; multi-agent orchestrators coordinate complex workflows
- Phased migration module files
- Backfill SQL scripts
- Rollout phase checklist
By the numbers
- 92 production-ready plugins with 88 local + 4 external via git-subdir
- 199 domain-expert agents spanning architecture, languages, infra, security, data, ML, docs, business
- 5 harnesses supported (Claude Code, Codex, Cursor, OpenCode, Gemini, Copilot)
Files
Database Migration
Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.
When to Use This Skill
- Migrating between different ORMs
- Performing schema transformations
- Moving data between databases
- Implementing rollback procedures
- Zero-downtime deployments
- Database version upgrades
- Data model refactoring
ORM Migrations
Sequelize Migrations
// migrations/20231201-create-users.js
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("users", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
email: {
type: Sequelize.STRING,
unique: true,
allowNull: false,
},
createdAt: Sequelize.DATE,
updatedAt: Sequelize.DATE,
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("users");
},
};
// Run: npx sequelize-cli db:migrate
// Rollback: npx sequelize-cli db:migrate:undoTypeORM Migrations
// migrations/1701234567-CreateUsers.ts
import { MigrationInterface, QueryRunner, Table } from "typeorm";
export class CreateUsers1701234567 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: "users",
columns: [
{
name: "id",
type: "int",
isPrimary: true,
isGenerated: true,
generationStrategy: "increment",
},
{
name: "email",
type: "varchar",
isUnique: true,
},
{
name: "created_at",
type: "timestamp",
default: "CURRENT_TIMESTAMP",
},
],
}),
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("users");
}
}
// Run: npm run typeorm migration:run
// Rollback: npm run typeorm migration:revertPrisma Migrations
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
createdAt DateTime @default(now())
}
// Generate migration: npx prisma migrate dev --name create_users
// Apply: npx prisma migrate deploySchema Transformations
Adding Columns with Defaults
// Safe migration: add column with default
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn("users", "status", {
type: Sequelize.STRING,
defaultValue: "active",
allowNull: false,
});
},
down: async (queryInterface) => {
await queryInterface.removeColumn("users", "status");
},
};Renaming Columns (Zero Downtime)
// Step 1: Add new column
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn("users", "full_name", {
type: Sequelize.STRING,
});
// Copy data from old column
await queryInterface.sequelize.query("UPDATE users SET full_name = name");
},
down: async (queryInterface) => {
await queryInterface.removeColumn("users", "full_name");
},
};
// Step 2: Update application to use new column
// Step 3: Remove old column
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn("users", "name");
},
down: async (queryInterface, Sequelize) => {
await queryInterface.addColumn("users", "name", {
type: Sequelize.STRING,
});
},
};Changing Column Types
module.exports = {
up: async (queryInterface, Sequelize) => {
// For large tables, use multi-step approach
// 1. Add new column
await queryInterface.addColumn("users", "age_new", {
type: Sequelize.INTEGER,
});
// 2. Copy and transform data
await queryInterface.sequelize.query(`
UPDATE users
SET age_new = CAST(age AS INTEGER)
WHERE age IS NOT NULL
`);
// 3. Drop old column
await queryInterface.removeColumn("users", "age");
// 4. Rename new column
await queryInterface.renameColumn("users", "age_new", "age");
},
down: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn("users", "age", {
type: Sequelize.STRING,
});
},
};Data Transformations
Complex Data Migration
module.exports = {
up: async (queryInterface, Sequelize) => {
// Get all records
const [users] = await queryInterface.sequelize.query(
"SELECT id, address_string FROM users",
);
// Transform each record
for (const user of users) {
const addressParts = user.address_string.split(",");
await queryInterface.sequelize.query(
`UPDATE users
SET street = :street,
city = :city,
state = :state
WHERE id = :id`,
{
replacements: {
id: user.id,
street: addressParts[0]?.trim(),
city: addressParts[1]?.trim(),
state: addressParts[2]?.trim(),
},
},
);
}
// Drop old column
await queryInterface.removeColumn("users", "address_string");
},
down: async (queryInterface, Sequelize) => {
// Reconstruct original column
await queryInterface.addColumn("users", "address_string", {
type: Sequelize.STRING,
});
await queryInterface.sequelize.query(`
UPDATE users
SET address_string = CONCAT(street, ', ', city, ', ', state)
`);
await queryInterface.removeColumn("users", "street");
await queryInterface.removeColumn("users", "city");
await queryInterface.removeColumn("users", "state");
},
};Rollback Strategies
Transaction-Based Migrations
module.exports = {
up: async (queryInterface, Sequelize) => {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
"users",
"verified",
{ type: Sequelize.BOOLEAN, defaultValue: false },
{ transaction },
);
await queryInterface.sequelize.query(
"UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",
{ transaction },
);
await transaction.commit();
} catch (error) {
await transaction.rollback();
throw error;
}
},
down: async (queryInterface) => {
await queryInterface.removeColumn("users", "verified");
},
};Checkpoint-Based Rollback
module.exports = {
up: async (queryInterface, Sequelize) => {
// Create backup table
await queryInterface.sequelize.query(
"CREATE TABLE users_backup AS SELECT * FROM users",
);
try {
// Perform migration
await queryInterface.addColumn("users", "new_field", {
type: Sequelize.STRING,
});
// Verify migration
const [result] = await queryInterface.sequelize.query(
"SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",
);
if (result[0].count > 0) {
throw new Error("Migration verification failed");
}
// Drop backup
await queryInterface.dropTable("users_backup");
} catch (error) {
// Restore from backup
await queryInterface.sequelize.query("DROP TABLE users");
await queryInterface.sequelize.query(
"CREATE TABLE users AS SELECT * FROM users_backup",
);
await queryInterface.dropTable("users_backup");
throw error;
}
},
};Additional patterns and templates
More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.
database-migration — additional patterns and templates
Zero-Downtime Migrations
Blue-Green Deployment Strategy
// Phase 1: Make changes backward compatible
module.exports = {
up: async (queryInterface, Sequelize) => {
// Add new column (both old and new code can work)
await queryInterface.addColumn("users", "email_new", {
type: Sequelize.STRING,
});
},
};
// Phase 2: Deploy code that writes to both columns
// Phase 3: Backfill data
module.exports = {
up: async (queryInterface) => {
await queryInterface.sequelize.query(`
UPDATE users
SET email_new = email
WHERE email_new IS NULL
`);
},
};
// Phase 4: Deploy code that reads from new column
// Phase 5: Remove old column
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn("users", "email");
},
};Cross-Database Migrations
PostgreSQL to MySQL
// Handle differences
module.exports = {
up: async (queryInterface, Sequelize) => {
const dialectName = queryInterface.sequelize.getDialect();
if (dialectName === "mysql") {
await queryInterface.createTable("users", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
data: {
type: Sequelize.JSON, // MySQL JSON type
},
});
} else if (dialectName === "postgres") {
await queryInterface.createTable("users", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
data: {
type: Sequelize.JSONB, // PostgreSQL JSONB type
},
});
}
},
};Related skills
How it compares
Use database-migration when you need phased, production-safe patterns rather than single-step dev-only ALTER examples.
FAQ
Do I install wshobson/agents into all five harnesses, or once?
Install once into your harness of choice; it ships idiomatic registries/artifacts for that harness (e.g., marketplace.json for Claude Code, .codex-plugin/ for Codex).
Can I use a single plugin across harnesses?
Yes - the Markdown plugin is source-of-truth; the make build process emits harness-native code. Codex and Cursor auto-read the committed registries; Gemini/OpenCode require clone + make generate.
Is Database Migration safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.