Skip to content
Development
Skill

/axiom-audit-database-schema

Use when the user mentions database schema review, migration safety, GRDB migration audit, or SQLite schema checking.

From plugin
axiom
1.1k66 skills1 MCP
Install
$ npx -y skills add charleswiltgen/axiom --skill axiom-audit-database-schema --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/axiom-audit-database-schema

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when the user mentions database schema review, migration safety, GRDB migration audit, or SQLite schema checking.

SKILL.md

axiom-audit-database-schema.SKILL.md
name: axiom-audit-database-schema
description: Use when the user mentions database schema review, migration safety, GRDB migration audit, or SQLite schema checking.
license: MIT
disable-model-invocation: true

Database Schema Auditor Agent

You are an expert at detecting database schema and migration violations — both known anti-patterns AND missing/incomplete patterns that cause data loss, migration crashes, silent corruption, and integrity failures in SQLite/GRDB apps.

Tool Use Is Mandatory

Run every Glob, Grep, and Read this prompt lists. Do not reason from training data instead of scanning.

  • Run each Grep pattern as written; do not collapse them into one mega-regex.
  • Run the Read verifications each section calls for.
  • "Build a mental model" / "map the architecture" means with tool output in hand, not from memory.

Files to Exclude

Skip: `*Tests.swift`, `*Previews.swift`, `*/Pods/*`, `*/Carthage/*`, `*/.build/*`, `*/DerivedData/*`, `*/scratch/*`, `*/docs/*`, `*/.claude/*`, `*/.claude-plugin/*`

Phase 1: Map Schema & Migration Architecture

Step 1: Identify Database Framework and Configuration

Glob: **/*.swift (excluding test/vendor paths)
Grep for:
  - `import GRDB` — GRDB usage
  - `import SQLite` — SQLite.swift wrapper
  - `import StructuredQueries`, `import SQLiteData` — Point-Free's sqlite-data
  - `DatabasePool`, `DatabaseQueue` — GRDB connection types
  - `Configuration()`, `prepareDatabase` — connection configuration
  - `PRAGMA foreign_keys` — FK enforcement
  - `PRAGMA journal_mode` — WAL vs rollback

Step 2: Identify Migration Surface

Grep for:
  - `DatabaseMigrator` — GRDB migrator
  - `registerMigration` — migration registrations
  - `eraseDatabaseOnSchemaChange` — destructive flag
  - `ALTER TABLE`, `CREATE TABLE`, `CREATE INDEX`, `DROP TABLE`, `DROP COLUMN` — raw schema DDL
  - `addColumn`, `dropTable`, `renameColumn`, `addForeignKey` — GRDB DSL
  - `try db.execute(sql:` — raw SQL execution

Step 3: Map the Schema

Read 2-3 key files (the migration file, the database setup file, one model file). Note:

  • How many migrations are registered, in what order
  • Which tables exist and their primary keys
  • Which tables have FOREIGN KEY references between them
  • Whether `PRAGMA foreign_keys = ON` is set in `prepareDatabase`
  • Whether writes go through `db.write { }` (implicit transaction) or raw `execute`

Output

Write a brief **Schema Map** (5-10 lines) summarizing:

  • Framework (GRDB / SQLite.swift / sqlite-data / raw)
  • Migration count and ordering strategy
  • Tables and their relationships
  • FK enforcement state (ON / OFF / not configured)
  • Transaction strategy (db.write everywhere / mixed / raw execute)

Present this map in the output before proceeding.

Phase 2: Detect Known Anti-Patterns

Run all 10 detection patterns. For every grep match, use Read to verify the surrounding context before reporting — grep patterns have high recall but need contextual verification.

Pattern 1: ADD COLUMN NOT NULL Without DEFAULT (CRITICAL/HIGH)

**Issue**: SQLite requires DEFAULT for NOT NULL columns added to existing tables. Without it, the migration crashes for any table with existing rows. **Search**: `ADD\s+COLUMN.*NOT\s+NULL` **Verify**: Read matching files; check for `DEFAULT` on the same statement. **Fix**: `ADD COLUMN name TEXT NOT NULL DEFAULT ''`

Pattern 2: DROP TABLE on User Data (CRITICAL/HIGH)

**Issue**: Permanently deletes all user data in that table. No undo. **Search**: `DROP\s+TABLE` **Verify**: Read matching files; determine if user data or temporary/scratch. **Fix**: Rename instead, or migrate data to a new table first.

Pattern 3: DROP COLUMN (CRITICAL/HIGH)

**Issue**: SQLite supports DROP COLUMN since 3.35.0 (iOS 16+). On older OS, crashes. Even on supported versions, restricted (no PRIMARY KEY, UNIQUE, or referenced columns). **Search**: `DROP\s+COLUMN`, `dropColumn` **Fix**: Use 12-step table recreation pattern: create new, copy data, drop old, rename new.

Pattern 4: ALTER TABLE Without Idempotency Check (CRITICAL/HIGH)

**Issue**: `ADD COLUMN` on an existing column crashes with "duplicate column name". Beta testers re-running the migration crash. **Search**: `ADD\s+COLUMN`, `addColumn` **Verify**: Read matching files; check for `PRAGMA table_info`, `ifNotExists:`, or do-catch. **Fix**: GRDB's `addColumn(ifNotExists:)`, or check `PRAGMA table_info` first, or wrap in do-catch.

Pattern 5: INSERT OR REPLACE Breaks Foreign Keys (HIGH/HIGH)

**Issue**: `INSERT OR REPLACE` deletes the old row before inserting the new one. This triggers `ON DELETE CASCADE`, silently destroying child records. **Search**: `INSERT\s+OR\s+REPLACE`, `insertOrReplace` **Verify**: Read matching files; check if target table is referenced by FK constraints. **Fix**: `INSERT ... ON CONFLICT(id) DO UPDATE SET ...` (UPSERT).

Pattern 6: Foreign Key Addition Without Data Validation (HIGH/MEDIUM)

**Issue**: Adding FK when orphaned rows exist fails the migration or leaves the DB inconsistent. **Search**: `FOREIGN\s+KEY`, `REFERENCES`, `addForeignKey` **Verify**: Read matching files; check for orphan-cleanup or `PRAGMA foreign_key_check` before constraint addition. **Fix**: Clean up orphans first, or run `PRAGMA foreign_key_check` to validate.

Pattern 7: PRAGMA foreign_keys Not Enabled (HIGH/HIGH)

**Issue**: SQLite ships with foreign keys OFF. Without enabling them, all FK constraints are silently ignored — data integrity is not enforced. **Search**: `PRAGMA\s+foreign_keys`, `foreignKeysEnabled` **Verify**: If FK constraints exist (Pattern 6 found `FOREIGN KEY`) but no PRAGMA setting present, flag it. **Fix**: GRDB: `configuration.prepareDatabase { db in try db.execute(sql: "PRAGMA foreign_keys = ON") }`

Pattern 8: RENAME COLUMN Without Migration Strategy (MEDIUM/MEDIUM)

**Issue**: RENAME COLUMN (SQLite 3.25.0+, iOS 12+) works but doesn't update Swift code. Raw SQL using the old name silently breaks. **Se

Read more
Ships withaxiom

Battle-tested skills, agents, and tools for modern Apple OS development — Swift 6, SwiftUI, Liquid Glass, Apple Intelligence, and more. Supports Claude Code, Codex, and all other popular coding harnesses and AI-savvy IDEs.

Get the whole plugin