Skip to content
Back to skills

Add Migration

ASecurity

Add a new database migration

  • 11 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
databasestypescriptgobashsqldatabase

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add lza6/Armor-piercing-system-prompts --skill add-migration --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Migration?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Migration
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lza6-add-migration/badge)](https://www.skillsdirectory.com/skills/lza6-add-migration)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: Add a new database migration
allowed-tools: Read, Glob, Grep, Edit, Bash(npm:*), Agent
argument-hint: <description>
---

# Add Migration

Add a new database migration to the project, following the established idempotent migration pattern.

**Usage:** `/add-migration <description>`

Example: `/add-migration Add priority column to tasks table`

**Arguments:** $ARGUMENTS

## Instructions

1. **Read current schema:**
   - Read `src/main/db/migrations.ts` to understand existing tables, columns, and migration patterns
   - Identify which migration function to modify: `runGlobalMigrations()` (for `index.db`) or `runProjectMigrations()` (for per-project `<projectId>.db`)
   - Most migrations go in `runProjectMigrations()` -- global is only for the projects list

2. **Determine migration type** and apply the correct pattern:

### Column Addition
```typescript
const hasColumn = (db.pragma('table_info(table_name)') as Array<{ name: string }>)
  .some((column) => column.name === 'new_column');
if (!hasColumn) {
  db.exec('ALTER TABLE table_name ADD COLUMN new_column TEXT DEFAULT NULL');
}
```

### Table Addition
```typescript
const hasTable = (db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get('new_table')) != null;
if (!hasTable) {
  db.exec(`CREATE TABLE new_table (
    id TEXT PRIMARY KEY,
    ...
  )`);
}
```

### Destructive Changes (column removal, type change, FK changes)
SQLite has no `ALTER TABLE DROP COLUMN` for older versions. Use table recreation:
```typescript
db.exec(`CREATE TABLE IF NOT EXISTS table_name_new (
  id TEXT PRIMARY KEY,
  ... -- new schema without the dropped column
)`);
db.exec('INSERT INTO table_name_new SELECT id, ... FROM table_name');
db.exec('DROP TABLE table_name');
db.exec('ALTER TABLE table_name_new RENAME TO table_name');
// Recreate any indexes
```

### Data Backfill
```typescript
const rows = db.prepare('SELECT id, config FROM table_name WHERE ...').all() as Array<{ id: string; config: string }>;
for (const row of rows) {
  try {
    const parsed = JSON.parse(row.config);
    // Transform data
    db.prepare('UPDATE table_name SET config = ? WHERE id = ?').run(JSON.stringify(parsed), row.id);
  } catch {
    // Skip malformed data
  }
}
```

3. **Placement rules:**
   - Add new migrations AFTER seed logic guards but BEFORE seed `INSERT` statements
   - Wrap multi-statement migrations in transactions if they involve data movement
   - Use `db.exec()` for DDL (CREATE, ALTER, DROP)
   - Use `db.prepare().run()` for parameterized DML (INSERT, UPDATE, DELETE)

4. **Match defaults to TypeScript types:**
   - Optional fields: `DEFAULT NULL`
   - Required strings: `DEFAULT ''`
   - Required numbers: `DEFAULT 0`
   - Required booleans: `DEFAULT 0` (SQLite uses 0/1)

5. **Update TypeScript types** in `src/shared/types.ts`:
   - Add new properties to the relevant interface (e.g., `Task`, `Swimlane`, `SessionRecord`)
   - Mark optional fields with `?` if `DEFAULT NULL`

6. **Update repository** in `src/main/db/repositories/`:
   - Add the new column to SELECT queries
   - Add the new column to INSERT/UPDATE queries
   - Add any new query methods needed

7. **Run typecheck:**
   - `npm run typecheck`
   - Fix any type errors

8. **Verify with the `migration-safety` agent (fresh context):**
   - Spawn the `migration-safety` agent (read-only: `Read`, `Glob`, `Grep`) to confirm the migration is idempotent (guarded by `pragma table_info` / `sqlite_master`), that DEFAULT values align with the TypeScript types, and that repository queries cover the new column.
   - This is delegation, not forking - the skill stays in the main loop and hands only the verification pass to the auditor for an unbiased check.
   - Fix any issues the auditor reports before finishing.

9. **Remind about docs:**
   - Suggest running `/sync-docs` to update `docs/database.md`

## Checklist

Before finalizing, verify:
- [ ] Migration is idempotent (safe to run multiple times)
- [ ] `pragma table_info` or `sqlite_master` guard is present
- [ ] DEFAULT value matches TypeScript type
- [ ] Repository queries include the new column
- [ ] TypeScript types updated
- [ ] Typecheck passes

## Allowed Tools

Use `Read`, `Glob`, `Grep`, `Edit`, `Bash` (for `npm run typecheck`), and `Agent` (to spawn the `migration-safety` verification agent at the end).

**CRITICAL: No chained commands.** Every Bash call must contain exactly ONE command. Never use `&&`, `||`, `|`, or `;`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in databases →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.