bun-drizzle-integration — Claude Code skill: Drizzle ORM on Bun SQLite
A skill that walks your agent through wiring Drizzle ORM to the bun:sqlite driver: schema, migrations, CRUD and transactions.
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a claude-codeWhat bun-drizzle-integration does
The skill kicks in when you build typed database access with Drizzle ORM on top of Bun's SQLite driver. It carries ready patterns: table definitions with sqliteTable, a drizzle.config.ts setup, and migration generation and application through drizzle-kit. Your agent pulls insert, select, update and delete examples from it, including onConflictDoNothing and upsert.
Relations get their own section, so relations, nested with queries, transactions with tx.rollback() and prepared statements are all covered. There is also a table of common failures: SQLITE_CONSTRAINT, no such column, Cannot find module. That last one points at the import path — pull the driver from anywhere but drizzle-orm/bun-sqlite and the types stop lining up.
Two packages come first: bun add drizzle-orm and bun add -D drizzle-kit. The skill references references/migrations.md and references/performance.md, worth loading for tricky migrations and performance work.
What it helps with
- define tables in
schema.tswith types and foreign keys - generate and apply migrations with
drizzle-kit - write an upsert that updates the conflicting row
- wrap several inserts in a transaction that can roll back
- fetch records together with their related rows in one query
Example prompts for the agent
- Define users and posts tables in
src/db/schema.tswithsqliteTableand link them throughrelations - Set up
drizzle.config.tsfor SQLite and generate a migration withbun drizzle-kit generate - Insert a user with
onConflictDoUpdateon email and return the row via.returning()
How to install bun-drizzle-integration
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a claude-code2Manually: put the files in place
~/.claude/skills/bun-drizzle-integration/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/bun-drizzle-integration/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a codex2Manually: put the files in place
.agents/skills/bun-drizzle-integration/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a cursor2Manually: put the files in place
.cursor/skills/bun-drizzle-integration/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install secondsky/claude-skills bun-drizzle-integration2Manually: put the files in place
.github/skills/bun-drizzle-integration/SKILL.md1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a gemini-cli2Platform CLI
gemini skills install https://github.com/secondsky/claude-skills --path plugins/bun/skills/bun-drizzle-integrationManually: put the files in place
.devin/skills/bun-drizzle-integration/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about bun-drizzle-integration
How do I install bun-drizzle-integration in Claude?
Run npx skills add secondsky/claude-skills --skill bun-drizzle-integration -a claude-code. The skill then lives at ~/.claude/skills/bun-drizzle-integration/SKILL.md.
What does bun-drizzle-integration do?
It gives your agent patterns for Drizzle ORM on the bun:sqlite driver: schema, config, migrations, CRUD, relations, transactions and prepared statements.
Which packages does the skill need?
drizzle-orm as a dependency and drizzle-kit as a dev dependency: bun add drizzle-orm and bun add -D drizzle-kit.
Source text
SKILL.md · MIT
---
name: bun-drizzle-integration
description: Use when integrating Drizzle ORM with Bun's SQLite driver for type-safe schema definitions and migrations.
metadata:
version: "1.0.0"
license: MIT
---
# Bun Drizzle Integration
Drizzle ORM provides type-safe database access with Bun's SQLite driver.
## Quick Start
```bash
bun add drizzle-orm
bun add -D drizzle-kit
```
## Schema Definition
```typescript
// src/db/schema.ts
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const users = sqliteTable("users", {
id: integer("id").primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
email: text("email").notNull().unique(),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.default(sql`(unixepoch())`),
});
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
content: text("content"),
authorId: integer("author_id")
.notNull()
.references(() => users.id),
});
```
## Database Setup
```typescript
// src/db/index.ts
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Database } from "bun:sqlite";
import * as schema from "./schema";
const sqlite = new Database("app.db");
export const db = drizzle(sqlite, { schema });
```
## Configuration
```typescript
// drizzle.config.ts
import type { Config } from "drizzle-kit";
export default {
schema: "./src/db/schema.ts",
out: "./drizzle",
dialect: "sqlite",
dbCredentials: {
url: "./app.db",
},
} satisfies Config;
```
## Migrations
```bash
# Generate migration
bun drizzle-kit generate
# Apply migrations
bun drizzle-kit migrate
# Push schema directly (dev only)
bun drizzle-kit push
# Open Drizzle Studio
bun drizzle-kit studio
```
## CRUD Operations
### Insert
```typescript
import { db } from "./db";
import { users, posts } from "./db/schema";
// Single insert
const user = await db.insert(users).values({
name: "Alice",
email: "[email protected]",
}).returning();
// Multiple insert
await db.insert(users).values([
{ name: "Bob", email: "[email protected]" },
{ name: "Charlie", email: "[email protected]" },
]);
// Insert or ignore
await db.insert(users)
.values({ name: "Alice", email: "[email protected]" })
.onConflictDoNothing();
// Upsert
await db.insert(users)
.values({ name: "Alice", email: "[email protected]" })
.onConflictDoUpdate({
target: users.email,
set: { name: "Alice Updated" },
});
```
### Select
```typescript
import { eq, gt, like, and, or, desc, asc } from "drizzle-orm";
// All rows
const allUsers = await db.select().from(users);
// With conditions
const activeUsers = await db
.select()
.from(users)
.where(eq(users.status, "active"));
// Multiple conditions
const filtered = await db
.select()
.from(users)
.where(and(
gt(users.age, 18),
like(users.name, "%Alice%")
));
// Specific columns
const names = await db
.select({ name: users.name, email: users.email })
.from(users);
// Order and limit
const topUsers = await db
.select()
.from(users)
.orderBy(desc(users.createdAt))
.limit(10);
// First result
const first = await db.query.users.findFirst({
where: eq(users.id, 1),
});
```
### Update
```typescript
// Update with condition
await db
.update(users)
.set({ name: "Alice Updated" })
.where(eq(users.id, 1));
// Update multiple fields
await db
.update(users)
.set({
name: "New Name",
updatedAt: new Date(),
})
.where(eq(users.email, "[email protected]"));
```
### Delete
```typescript
// Delete with condition
await db.delete(users).where(eq(users.id, 1));
// Delete multiple
await db.delete(users).where(gt(users.createdAt, cutoffDate));
```
## Relations
```typescript
// schema.ts
import { relations } from "drizzle-orm";
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));
// Query with relations
const usersWithPosts = await db.query.users.findMany({
with: {
posts: true,
},
});
// Nested relations
const detailed = await db.query.users.findFirst({
where: eq(users.id, 1),
with: {
posts: {
with: {
comments: true,
},
},
},
});
```
## Transactions
```typescript
// Transaction
await db.transaction(async (tx) => {
const [user] = await tx.insert(users)
.values({ name: "Alice", email: "[email protected]" })
.returning();
await tx.insert(posts).values({
title: "First Post",
authorId: user.id,
});
});
// Rollback on error
await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Bob" });
if (someCondition) {
tx.rollback(); // Throws to rollback
}
await tx.insert(posts).values({ ... });
});
```
## Prepared Statements
```typescript
// Create prepared statement
const getUserById = db
.select()
.from(users)
.where(eq(users.id, sql.placeholder("id")))
.prepare();
// Execute with parameter
const user = await getUserById.execute({ id: 1 });
// Reuse for performance
for (const id of userIds) {
const user = await getUserById.execute({ id });
processUser(user);
}
```
## Raw SQL
```typescript
import { sql } from "drizzle-orm";
// Raw query
const result = await db.run(sql`
UPDATE users SET last_login = ${new Date()} WHERE id = ${userId}
`);
// In select
const users = await db.select({
name: users.name,
upperName: sql<string>`UPPER(${users.name})`,
}).from(users);
// Raw expressions in where
await db.select().from(users).where(
sql`${users.age} > 18 AND ${users.status} = 'active'`
);
```
## Column Types Reference
```typescript
import {
sqliteTable,
text,
integer,
real,
blob,
numeric,
} from "drizzle-orm/sqlite-core";
const example = sqliteTable("example", {
// Integer
id: integer("id").primaryKey(),
age: integer("age"),
// Text
name: text("name"),
status: text("status", { enum: ["active", "inactive"] }),
// Real (float)
price: real("price"),
// Blob
data: blob("data", { mode: "buffer" }),
// Boolean (stored as integer)
active: integer("active", { mode: "boolean" }),
// Timestamp (stored as integer)
createdAt: integer("created_at", { mode: "timestamp" }),
updatedMs: integer("updated_ms", { mode: "timestamp_ms" }),
// JSON (stored as text)
metadata: text("metadata", { mode: "json" }),
});
```
## Common Errors
| Error | Cause | Fix |
|-------|-------|-----|
| `SQLITE_CONSTRAINT` | FK/unique violation | Check constraints |
| `no such column` | Schema mismatch | Run migrations |
| `Cannot find module` | Missing driver | Use `drizzle-orm/bun-sqlite` |
| Type mismatch | Wrong column type | Check schema definition |
## When to Load References
Load `references/migrations.md` when:
- Complex migration scenarios
- Migration squashing
- Database seeding
Load `references/performance.md` when:
- Query optimization
- Indexing strategies
- Connection pooling
© secondsky · MIT · secondsky/claude-skills