database-schema
54
总安装量
53
周安装量
#3989
全站排名
安装命令
npx skills add https://github.com/alinaqi/claude-bootstrap --skill database-schema
Agent 安装分布
claude-code
45
opencode
42
gemini-cli
41
antigravity
38
cursor
36
codex
35
Skill 文档
Database Schema Awareness Skill
Load with: base.md + [your database 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), primary_key=True, default=uuid.uuid4)
email = Column(String, nullable=False, unique=True)
name = Column(String, nullable=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
# Relationships
orders = relationship("Order", back_populates="user")
# app/schemas/user.py - Pydantic for API validation
from pydantic import BaseModel, EmailStr
from uuid import UUID
from datetime import datetime
class UserBase(BaseModel):
email: EmailStr
name: str | None = None
class UserCreate(UserBase):
pass
class User(UserBase):
id: UUID
created_at: datetime
class Config:
from_attributes = True
Schema-Aware TDD Workflow
Extend the standard TDD workflow for database work:
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 0. SCHEMA: Read and verify schema before anything else â
â ââ Read schema file â
â ââ Complete Schema Verification Checklist â
â ââ Note any missing columns/tables needed â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 1. RED: Write tests that use correct column names â
â ââ Import generated types â
â ââ Use type-safe queries in tests â
â ââ Tests should fail on logic, NOT schema errors â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 2. GREEN: Implement with type-safe queries â
â ââ Use ORM types, not raw strings â
â ââ TypeScript/mypy catches column mismatches â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 3. VALIDATE: Type check catches schema drift â
â ââ tsc --noEmit / mypy catches wrong columns â
â ââ Tests validate runtime behavior â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Common Schema Mistakes (And How to Prevent)
| Mistake | Example | Prevention |
|---|---|---|
| Wrong column name | user.userName vs user.name |
Read schema, use generated types |
| Wrong type | totalCents as string |
Type generation catches this |
| Missing nullable check | user.name! when nullable |
Schema shows nullable fields |
| Wrong FK relationship | order.userId vs order.user_id |
Check schema column names |
| Missing column | Using user.avatar that doesn’t exist |
Read schema before coding |
| Wrong enum value | status: 'complete' vs 'completed' |
Document enums in schema reference |
Type-Safe Query Examples
Drizzle (catches errors at compile time):
// â
Correct - uses schema-defined columns
const user = await db.select().from(users).where(eq(users.email, email));
// â Wrong - TypeScript error: 'userName' doesn't exist
const user = await db.select().from(users).where(eq(users.userName, email));
Prisma (catches errors at compile time):
// â
Correct
const user = await prisma.user.findUnique({ where: { email } });
// â Wrong - TypeScript error
const user = await prisma.user.findUnique({ where: { userName: email } });
Raw SQL (NO protection – avoid):
// â Dangerous - no type checking, easy to get wrong
const result = await db.query('SELECT * FROM users WHERE user_name = $1', [email]);
// Should be 'email' not 'user_name' - won't catch until runtime
Migration Workflow
When schema changes are needed:
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 1. Update schema file (Drizzle/Prisma/SQLAlchemy) â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 2. Generate migration â
â ââ Drizzle: npx drizzle-kit generate â
â ââ Prisma: npx prisma migrate dev --name add_column â
â ââ Supabase: supabase migration new add_column â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 3. Regenerate types â
â ââ Prisma: npx prisma generate â
â ââ Supabase: supabase gen types typescript â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 4. Update schema-reference.md â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 5. Run type check - find all broken code â
â ââ npm run typecheck â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â 6. Fix type errors, update tests, run full validation â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Session Start Protocol
When starting a session that involves database work:
- Read schema file immediately
- Read
_project_specs/schema-reference.mdif exists - Note in session state what tables/columns are relevant
- Reference schema explicitly when writing code
Session state example:
## Current Session - Database Context
**Schema read:** â src/db/schema.ts
**Tables in scope:** users, orders, order_items
**Key columns:**
- users: id, email, name, created_at
- orders: id, user_id, status, total_cents
- order_items: id, order_id, product_id, quantity, price_cents
Anti-Patterns
- â Guessing column names – Always read schema first
- â Using raw SQL strings – Use ORM with type generation
- â Hardcoding without verification – Check schema before using any column
- â Ignoring type errors – Schema drift shows up as type errors
- â Not regenerating types – After migration, always regenerate
- â Assuming nullable – Check schema for nullable columns
Checklist
Setup
- Schema file exists in standard location
- Type generation configured
-
_project_specs/schema-reference.mdcreated - Types regenerate on schema change
Per-Task
- Schema read before writing database code
- Schema Verification Checklist completed
- Using generated types (not raw strings)
- Type check passes (catches column errors)
- Tests use correct schema