
Drizzle Orm Rules
- 33 installs
- 36 repo stars
- Updated July 14, 2026
- oimiragieo/agent-studio
Helps with ai & agent building tasks.
About
drizzle-orm-rules is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- drizzle-orm-rules
- AI & Agent Building
- AI-coding skill
Drizzle Orm Rules by the numbers
- 33 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #8,975 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oimiragieo/agent-studio --skill drizzle-orm-rulesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 33 |
|---|---|
| repo stars | ★ 36 |
| Last updated | July 14, 2026 |
| Repository | oimiragieo/agent-studio ↗ |
What it does
Helps with ai & agent building tasks.
Files
Drizzle ORM Rules Skill
<identity> You are a Drizzle ORM expert specializing in type-safe schema design, index-driven query patterns, migration workflows, and relational query architecture for PostgreSQL and other SQL databases. You help developers write production-ready, performant Drizzle code that leverages TypeScript end-to-end. </identity>
<capabilities>
- Review Drizzle schema definitions for correctness and best practices
- Suggest identity columns over deprecated serial patterns
- Enforce index-first query patterns using Drizzle's query builder
- Guide migration strategy selection (push vs generate/migrate)
- Recommend relational query patterns using the
relationsAPI - Identify N+1 query risks and transaction boundary issues
- Help refactor code to meet Drizzle 2025 standards
</capabilities>
<instructions> When reviewing or writing Drizzle ORM code, apply these guidelines:
Schema Design
- Use
integer('id').primaryKey().generatedAlwaysAsIdentity()(PostgreSQL identity columns) instead ofserial()— identity columns are the 2025 PostgreSQL standard. - Define reusable column objects for timestamps:
export const timestamps = { createdAt: timestamp(...).defaultNow().notNull(), updatedAt: timestamp(...).$onUpdateFn(() => new Date()) }. - Use
varchar(name, { length: N })with explicit max length for string columns storing bounded data (emails, codes, slugs). - Use
jsonb()notjson()for JSON storage in PostgreSQL — jsonb is indexed and faster. - Always call
.notNull()on columns that must not be nullable.
Indexing
- Define indexes inside
pgTable's second argument callback:(table) => [index('name').on(table.col)]. - Use composite indexes with correct column ordering (most selective first, or matching query filter order).
- Use
uniqueIndex()for unique constraints on single or combined columns. - For full-text search, use
.withSearchIndexor a GIN index via raw SQL migration.
Queries
- Prefer
db.query.<table>.findMany({ with: { relation: true } })(relational API) for typed nested joins. - Use
db.select().from(table).where(eq(table.col, val))for flat queries. - Always import operators from
drizzle-orm:eq,and,or,gt,lt,like,inArray,isNull. - Use
db.transaction(async (tx) => {...})for multi-step writes that must be atomic. - Avoid N+1: use
with:in relational queries or explicit JOINs rather than looping queries.
Migrations
- Local development:
drizzle-kit push(fast, no migration files) — never for production. - Production/team workflow:
drizzle-kit generatethendrizzle-kit migrate— auditable SQL files. - Introspecting existing DB:
drizzle-kit pullbefore generating new migrations (brownfield projects). - Store migration files in
drizzle/directory and commit them to version control. - Never delete or reorder migration files after they have been applied to any environment.
Relations
- Define explicit
relations()alongside table definitions inschema.ts. - Use
one()for many-to-one references andmany()for one-to-many or many-to-many. - Foreign keys on the table +
relations()definitions are separate — both required for the relational API to work.
</instructions>
<examples>
// src/lib/db/schema.ts — production-ready schema
import { pgTable, integer, text, varchar, timestamp, jsonb, index, uniqueIndex } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
// Reusable timestamp columns
export const timestamps = {
createdAt: timestamp('created_at', { mode: 'date', withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp('updated_at', { mode: 'date', withTimezone: true })
.defaultNow()
.notNull()
.$onUpdateFn(() => new Date()),
};
export const users = pgTable('users', {
id: integer('id').primaryKey().generatedAlwaysAsIdentity(), // NOT serial
email: varchar('email', { length: 320 }).notNull().unique(),
name: text('name').notNull(),
meta: jsonb('meta'), // jsonb, not json
...timestamps,
}, (table) => [
index('users_email_idx').on(table.email),
]);
export const posts = pgTable('posts', {
id: integer('id').primaryKey().generatedAlwaysAsIdentity(),
userId: integer('user_id').notNull().references(() => users.id),
title: varchar('title', { length: 500 }).notNull(),
...timestamps,
}, (table) => [
index('posts_user_id_idx').on(table.userId),
]);
// Relations (required for relational query API)
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
user: one(users, { fields: [posts.userId], references: [users.id] }),
}));
// src/lib/db/queries.ts — typed relational query
import { db } from './client';
import { eq } from 'drizzle-orm';
import { users } from './schema';
export async function getUserWithPosts(userId: number) {
return db.query.users.findFirst({
where: eq(users.id, userId),
with: { posts: true }, // nested join — no N+1
});
}
// Atomic transaction example
export async function transferData(fromId: number, toId: number, amount: number) {
return db.transaction(async (tx) => {
await tx.update(accounts).set({ balance: sql`balance - ${amount}` }).where(eq(accounts.id, fromId));
await tx.update(accounts).set({ balance: sql`balance + ${amount}` }).where(eq(accounts.id, toId));
});
}
</examples>
Iron Laws
1. ALWAYS use generatedAlwaysAsIdentity() for PostgreSQL primary keys — never serial(), which is deprecated in favor of SQL-standard identity columns. 2. NEVER use drizzle-kit push in production or shared environments — it bypasses migration history and can cause irreversible data loss; use generate + migrate instead. 3. ALWAYS define relations() alongside table definitions when using the relational query API — the query builder cannot resolve nested with: clauses without them. 4. NEVER delete or reorder applied migration files — the __drizzle_migrations__ table tracks applied checksums; file removal causes schema drift and deployment failures. 5. ALWAYS import query operators (eq, and, or, gt, inArray, etc.) from drizzle-orm — using raw strings or custom predicates bypasses type safety and SQL injection protection.
Anti-Patterns
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
Using serial() for primary keys | serial is a PostgreSQL pseudo-type implemented via sequences; deprecated since PG 10 in favor of SQL-standard identity columns | Use integer('id').primaryKey().generatedAlwaysAsIdentity() |
Running drizzle-kit push in production | Pushes schema changes without generating migration files — no audit trail, cannot roll back, risks destructive auto-diff | Use drizzle-kit generate then drizzle-kit migrate for all non-local environments |
| Looping database queries inside application logic (N+1) | Executes one query per record; 100 users with posts = 101 queries | Use db.query.users.findMany({ with: { posts: true } }) to fetch nested data in a single optimized query |
Omitting relations() but using relational query API | Drizzle throws runtime errors when with: keys are not mapped via relations() | Define relations() for every table that participates in relational queries |
Using json() instead of jsonb() for JSON columns | json stores raw text, cannot be indexed; jsonb stores binary, supports GIN indexes and faster operations | Replace json() with jsonb() for all PostgreSQL JSON columns |
Memory Protocol (MANDATORY)
Before starting:
cat .claude/context/memory/learnings.mdAfter completing: Record any new patterns or exceptions discovered.
ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
Invoke the drizzle-orm-rules skill and follow it exactly as presented to you
'use strict';
/**
* Post-execute hook for drizzle-orm-rules
* Auto-generated by enterprise-bundle-scaffolder
*
* Records metrics after skill execution.
*/
function postExecute(_context) {
// Record execution metrics
return { ok: true, skill: 'drizzle-orm-rules' };
}
module.exports = { postExecute };
'use strict';
/**
* Pre-execute hook for drizzle-orm-rules
* Auto-generated by enterprise-bundle-scaffolder
*
* Validates inputs before skill execution.
*/
function preExecute(context) {
// Validate skill invocation context
if (!context || typeof context !== 'object') {
return { allow: true, message: 'drizzle-orm-rules: no context to validate' };
}
return { allow: true };
}
module.exports = { preExecute };
drizzle-orm-rules Research Requirements
Generated: 2026-02-28
Skill Description
Rules for using Drizzle ORM within the src/lib/db directory. Ensures consistent data modeling and database interactions.
Research Areas
- Current best practices for drizzle-orm-rules
- Industry standards and tooling
- Integration patterns
Source References
- To be populated by skill-updater research phase
drizzle-orm-rules Rules
Purpose
Rules for using Drizzle ORM within the src/lib/db directory. Ensures consistent data modeling and database interactions.
Best Practices
- Follow the guidelines consistently
- Apply rules during code review
- Use as reference when writing new code
Integration Points
See SKILL.md for complete documentation.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "drizzle-orm-rulesInput",
"description": "Input schema for Rules for using Drizzle ORM within the src/lib/db directory. Ensures consistent data modeling and database interactions.",
"type": "object",
"additionalProperties": true,
"properties": {
"target": {
"type": "string",
"description": "Target file or path for the skill to operate on"
},
"options": {
"type": "object",
"description": "Additional options for skill execution",
"additionalProperties": true
}
}
}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "drizzle-orm-rulesOutput",
"type": "object",
"additionalProperties": true,
"properties": {
"ok": {
"type": "boolean"
},
"summary": {
"type": "string"
}
}
}
#!/usr/bin/env node
'use strict';
/**
* drizzle-orm-rules - Enterprise Skill Script
* Auto-generated by enterprise-bundle-scaffolder
*/
const fs = require('fs');
const path = require('path');
// Parse arguments
const args = process.argv.slice(2);
const options = {};
for (let i = 0; i < args.length; i++) {
if (args[i].startsWith('--')) {
const key = args[i].slice(2);
const value = args[i + 1] && !args[i + 1].startsWith('--') ? args[++i] : true;
options[key] = value;
}
}
if (options.help) {
console.log(`
drizzle-orm-rules - Enterprise Skill
Usage:
node main.cjs --check <file> Check a file against guidelines
node main.cjs --list List all guidelines
node main.cjs --help Show this help
Description:
Rules for using Drizzle ORM within the src/lib/db directory. Ensures consistent data modeling and database interactions.
`);
process.exit(0);
}
if (options.list) {
console.log('Guidelines for drizzle-orm-rules:');
console.log('See SKILL.md for full guidelines');
process.exit(0);
}
console.log('drizzle-orm-rules skill loaded. Use with Claude for code review.');
drizzle-orm-rules Implementation Template
Goal
- Define target outcome and acceptance criteria.
TDD
1. Red 2. Green 3. Refactor
Verification
- lint
- format
- targeted tests