/database-schema
Schema awareness - read before coding, type generation, prevent column errors
Claude Code
$ npx -y skills add alinaqi/maggy --skill database-schema --agent claude-code
Codex
$ npx skills add alinaqi/maggy --skill database-schema -a codex -y
Cursor
$ npx skills add alinaqi/maggy --skill database-schema -a cursor -y
Gemini CLI
$ npx skills add alinaqi/maggy --skill database-schema -a gemini-cli -y
GitHub Copilot
$ npx skills add alinaqi/maggy --skill database-schema -a github-copilot -y
OpenCode
$ npx skills add alinaqi/maggy --skill database-schema -a opencode -y
Windsurf
$ npx skills add alinaqi/maggy --skill database-schema -a windsurf -y
SKILL.md
database-schema.SKILL.mdname: database-schema
description: Schema awareness - read before coding, type generation, prevent column errors
when-to-use: Before writing any database queries or modifying data models
user-invocable: false
paths: ["**/schema.*", "**/migrations/**", "**/models/**", "**/*.prisma", "**/drizzle/**"]
effort: medium
Database Schema Awareness Skill
**Problem:** Claude forgets schema details mid-session - wrong column names, missing fields, incorrect types. TDD catches this at runtime, but we can prevent it earlier.
---
Core Rule: Read Schema Before Writing Database Code
**MANDATORY: Before writing ANY code that touches the database:**
┌─────────────────────────────────────────────────────────────┐
│ 1. READ the schema file (see locations below) │
│ 2. VERIFY columns/types you're about to use exist │
│ 3. REFERENCE schema in your response when writing queries │
│ 4. TYPE-CHECK using generated types (Drizzle/Prisma/etc) │
└─────────────────────────────────────────────────────────────┘
**If schema file doesn't exist → CREATE IT before proceeding.**
---
Schema File Locations (By Stack)
| Stack | Schema Location | Type Generation | |-------|-----------------|-----------------| | **Drizzle** | `src/db/schema.ts` or `drizzle/schema.ts` | Built-in TypeScript | | **Prisma** | `prisma/schema.prisma` | `npx prisma generate` | | **Supabase** | `supabase/migrations/*.sql` + types | `supabase gen types typescript` | | **SQLAlchemy** | `app/models/*.py` or `src/models.py` | Pydantic models | | **TypeORM** | `src/entities/*.ts` | Decorators = types | | **Raw SQL** | `schema.sql` or `migrations/` | Manual types required |
Schema Reference File (Recommended)
Create `_project_specs/schema-reference.md` for quick lookup:
# Database Schema Reference
*Auto-generated or manually maintained. Claude: READ THIS before database work.*
## Tables
### users
| Column | Type | Nullable | Default | Notes |
|--------|------|----------|---------|-------|
| id | uuid | NO | gen_random_uuid() | PK |
| email | text | NO | - | Unique |
| name | text | YES | - | Display name |
| created_at | timestamptz | NO | now() | - |
| updated_at | timestamptz | NO | now() | - |
### orders
| Column | Type | Nullable | Default | Notes |
|--------|------|----------|---------|-------|
| id | uuid | NO | gen_random_uuid() | PK |
| user_id | uuid | NO | - | FK → users.id |
| status | text | NO | 'pending' | enum: pending/paid/shipped/delivered |
| total_cents | integer | NO | - | Amount in cents |
| created_at | timestamptz | NO | now() | - |
## Relationships
- users 1:N orders (user_id)
## Enums
- order_status: pending, paid, shipped, delivered
---
Pre-Code Checklist (Database Work)
Before writing any database code, Claude MUST:
### Schema Verification Checklist
- [ ] Read schema file: `[path to schema]`
- [ ] Columns I'm using exist: [list columns]
- [ ] Types match my code: [list type mappings]
- [ ] Relationships are correct: [list FKs]
- [ ] Nullable fields handled: [list nullable columns]
**Example in practice:**
### Schema Verification for TODO-042 (Add order history endpoint)
- [x] Read schema: `src/db/schema.ts`
- [x] Columns exist: orders.id, orders.user_id, orders.status, orders.total_cents, orders.created_at
- [x] Types: id=uuid→string, total_cents=integer→number, status=text→OrderStatus enum
- [x] Relationships: orders.user_id → users.id (many-to-one)
- [x] Nullable: none of these columns are nullable
---
Type Generation Commands
Drizzle (TypeScript)
// Schema defines types automatically
// src/db/schema.ts
import { pgTable, uuid, text, integer, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
export const orders = pgTable('orders', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id),
status: text('status').notNull().default('pending'),
totalCents: integer('total_cents').notNull(),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
// Inferred types - USE THESE
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
export type Order = typeof orders.$inferSelect;
export type NewOrder = typeof orders.$inferInsert;Prisma
// prisma/schema.prisma
model User {
id String @id @default(uuid())
email String @unique
name String?
orders Order[]
createdAt DateTime @default(now()) @map("created_at")
@@map("users")
}
model Order {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
status String @default("pending")
totalCents Int @map("total_cents")
createdAt DateTime @default(now()) @map("created_at")
@@map("orders")
}# Generate types after schema changes
npx prisma generate
Supabase
# Generate TypeScript types from live database
supabase gen types typescript --local > src/types/database.ts
# Or from remote
supabase gen types typescript --project-id your-project-id > src/types/database.ts
// Use generated types
import { Database } from '@/types/database';
type User = Database['public']['Tables']['users']['Row'];
type NewUser = Database['public']['Tables']['users']['Insert'];
type Order = Database['public']['Tables']['orders']['Row'];SQLAlchemy (Python)
# app/models/user.py
from sqlalchemy import Column, String, DateTime
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from app.db import Base
import uuid
class User(Base):
__tablename__ = "users"
id = Column(UUID(as_uuid=True), primaryRead more
name: database-schema description: Schema awareness - read before coding, type generation, prevent column errors when-to-use: Before writing any database queries or modifying data models user-invocable: false paths: ["**/schema.*", "**/migrations/**", "**/models/**", "**/*.prisma", "**/drizzle/**"] effort: medium
Database Schema Awareness Skill
**Problem:** Claude forgets schema details mid-session - wrong column names, missing fields, incorrect types. TDD catches this at runtime, but we can prevent it earlier.
---
Core Rule: Read Schema Before Writing Database Code
**MANDATORY: Before writing ANY code that touches the database:**
┌─────────────────────────────────────────────────────────────┐ │ 1. READ the schema file (see locations below) │ │ 2. VERIFY columns/types you're about to use exist │ │ 3. REFERENCE schema in your response when writing queries │ │ 4. TYPE-CHECK using generated types (Drizzle/Prisma/etc) │ └─────────────────────────────────────────────────────────────┘
**If schema file doesn't exist → CREATE IT before proceeding.**
---
Schema File Locations (By Stack)
| Stack | Schema Location | Type Generation | |-------|-----------------|-----------------| | **Drizzle** | `src/db/schema.ts` or `drizzle/schema.ts` | Built-in TypeScript | | **Prisma** | `prisma/schema.prisma` | `npx prisma generate` | | **Supabase** | `supabase/migrations/*.sql` + types | `supabase gen types typescript` | | **SQLAlchemy** | `app/models/*.py` or `src/models.py` | Pydantic models | | **TypeORM** | `src/entities/*.ts` | Decorators = types | | **Raw SQL** | `schema.sql` or `migrations/` | Manual types required |
Schema Reference File (Recommended)
Create `_project_specs/schema-reference.md` for quick lookup:
# Database Schema Reference *Auto-generated or manually maintained. Claude: READ THIS before database work.* ## Tables ### users | Column | Type | Nullable | Default | Notes | |--------|------|----------|---------|-------| | id | uuid | NO | gen_random_uuid() | PK | | email | text | NO | - | Unique | | name | text | YES | - | Display name | | created_at | timestamptz | NO | now() | - | | updated_at | timestamptz | NO | now() | - | ### orders | Column | Type | Nullable | Default | Notes | |--------|------|----------|---------|-------| | id | uuid | NO | gen_random_uuid() | PK | | user_id | uuid | NO | - | FK → users.id | | status | text | NO | 'pending' | enum: pending/paid/shipped/delivered | | total_cents | integer | NO | - | Amount in cents | | created_at | timestamptz | NO | now() | - | ## Relationships - users 1:N orders (user_id) ## Enums - order_status: pending, paid, shipped, delivered
---
Pre-Code Checklist (Database Work)
Before writing any database code, Claude MUST:
### Schema Verification Checklist - [ ] Read schema file: `[path to schema]` - [ ] Columns I'm using exist: [list columns] - [ ] Types match my code: [list type mappings] - [ ] Relationships are correct: [list FKs] - [ ] Nullable fields handled: [list nullable columns]
**Example in practice:**
### Schema Verification for TODO-042 (Add order history endpoint) - [x] Read schema: `src/db/schema.ts` - [x] Columns exist: orders.id, orders.user_id, orders.status, orders.total_cents, orders.created_at - [x] Types: id=uuid→string, total_cents=integer→number, status=text→OrderStatus enum - [x] Relationships: orders.user_id → users.id (many-to-one) - [x] Nullable: none of these columns are nullable
---
Type Generation Commands
Drizzle (TypeScript)
// Schema defines types automatically
// src/db/schema.ts
import { pgTable, uuid, text, integer, timestamp } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull().unique(),
name: text('name'),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
export const orders = pgTable('orders', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id),
status: text('status').notNull().default('pending'),
totalCents: integer('total_cents').notNull(),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
// Inferred types - USE THESE
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
export type Order = typeof orders.$inferSelect;
export type NewOrder = typeof orders.$inferInsert;Prisma
// prisma/schema.prisma
model User {
id String @id @default(uuid())
email String @unique
name String?
orders Order[]
createdAt DateTime @default(now()) @map("created_at")
@@map("users")
}
model Order {
id String @id @default(uuid())
userId String @map("user_id")
user User @relation(fields: [userId], references: [id])
status String @default("pending")
totalCents Int @map("total_cents")
createdAt DateTime @default(now()) @map("created_at")
@@map("orders")
}# Generate types after schema changes npx prisma generate
Supabase
# Generate TypeScript types from live database supabase gen types typescript --local > src/types/database.ts # Or from remote supabase gen types typescript --project-id your-project-id > src/types/database.ts
// Use generated types
import { Database } from '@/types/database';
type User = Database['public']['Tables']['users']['Row'];
type NewUser = Database['public']['Tables']['users']['Insert'];
type Order = Database['public']['Tables']['orders']['Row'];SQLAlchemy (Python)
# app/models/user.py
from sqlalchemy import Column, String, DateTime
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from app.db import Base
import uuid
class User(Base):
__tablename__ = "users"
id = Column(UUID(as_uuid=True), primaryTurn Claude Code into a self-reviewing, test-enforced engineering system that remembers context across sessions — then route work across 13 models from a single dashboard.
Other skills on maggy.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about database-schema.
- Which coding agents can use database-schema?
- database-schema installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

