Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    lobehub

    drizzle

    lobehub/drizzle
    Data & Analytics
    72,111
    7 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Drizzle ORM schema and database guide. Use when working with database schemas (src/database/schemas/*), defining tables, creating migrations, or database model code...

    SKILL.md

    Drizzle ORM Schema Style Guide

    Configuration

    • Config: drizzle.config.ts
    • Schemas: src/database/schemas/
    • Migrations: src/database/migrations/
    • Dialect: postgresql with strict: true

    Helper Functions

    Location: src/database/schemas/_helpers.ts

    • timestamptz(name): Timestamp with timezone
    • createdAt(), updatedAt(), accessedAt(): Standard timestamp columns
    • timestamps: Object with all three for easy spread

    Naming Conventions

    • Tables: Plural snake_case (users, session_groups)
    • Columns: snake_case (user_id, created_at)

    Column Definitions

    Primary Keys

    id: text('id')
      .primaryKey()
      .$defaultFn(() => idGenerator('agents'))
      .notNull(),
    

    ID prefixes make entity types distinguishable. For internal tables, use uuid.

    Foreign Keys

    userId: text('user_id')
      .references(() => users.id, { onDelete: 'cascade' })
      .notNull(),
    

    Timestamps

    ...timestamps,  // Spread from _helpers.ts
    

    Indexes

    // Return array (object style deprecated)
    (t) => [uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId)],
    

    Type Inference

    export const insertAgentSchema = createInsertSchema(agents);
    export type NewAgent = typeof agents.$inferInsert;
    export type AgentItem = typeof agents.$inferSelect;
    

    Example Pattern

    export const agents = pgTable(
      'agents',
      {
        id: text('id')
          .primaryKey()
          .$defaultFn(() => idGenerator('agents'))
          .notNull(),
        slug: varchar('slug', { length: 100 })
          .$defaultFn(() => randomSlug(4))
          .unique(),
        userId: text('user_id')
          .references(() => users.id, { onDelete: 'cascade' })
          .notNull(),
        clientId: text('client_id'),
        chatConfig: jsonb('chat_config').$type<LobeAgentChatConfig>(),
        ...timestamps,
      },
      (t) => [uniqueIndex('client_id_user_id_unique').on(t.clientId, t.userId)],
    );
    

    Common Patterns

    Junction Tables (Many-to-Many)

    export const agentsKnowledgeBases = pgTable(
      'agents_knowledge_bases',
      {
        agentId: text('agent_id')
          .references(() => agents.id, { onDelete: 'cascade' })
          .notNull(),
        knowledgeBaseId: text('knowledge_base_id')
          .references(() => knowledgeBases.id, { onDelete: 'cascade' })
          .notNull(),
        userId: text('user_id')
          .references(() => users.id, { onDelete: 'cascade' })
          .notNull(),
        enabled: boolean('enabled').default(true),
        ...timestamps,
      },
      (t) => [primaryKey({ columns: [t.agentId, t.knowledgeBaseId] })],
    );
    

    Query Style

    Always use db.select() builder API. Never use db.query.* relational API (findMany, findFirst, with:).

    The relational API generates complex lateral joins with json_build_array that are fragile and hard to debug.

    Select Single Row

    // ✅ Good
    const [result] = await this.db
      .select()
      .from(agents)
      .where(eq(agents.id, id))
      .limit(1);
    return result;
    
    // ❌ Bad: relational API
    return this.db.query.agents.findFirst({
      where: eq(agents.id, id),
    });
    

    Select with JOIN

    // ✅ Good: explicit select + leftJoin
    const rows = await this.db
      .select({
        runId: agentEvalRunTopics.runId,
        score: agentEvalRunTopics.score,
        testCase: agentEvalTestCases,
        topic: topics,
      })
      .from(agentEvalRunTopics)
      .leftJoin(agentEvalTestCases, eq(agentEvalRunTopics.testCaseId, agentEvalTestCases.id))
      .leftJoin(topics, eq(agentEvalRunTopics.topicId, topics.id))
      .where(eq(agentEvalRunTopics.runId, runId))
      .orderBy(asc(agentEvalRunTopics.createdAt));
    
    // ❌ Bad: relational API with `with:`
    return this.db.query.agentEvalRunTopics.findMany({
      where: eq(agentEvalRunTopics.runId, runId),
      with: { testCase: true, topic: true },
    });
    

    Select with Aggregation

    // ✅ Good: select + leftJoin + groupBy
    const rows = await this.db
      .select({
        id: agentEvalDatasets.id,
        name: agentEvalDatasets.name,
        testCaseCount: count(agentEvalTestCases.id).as('testCaseCount'),
      })
      .from(agentEvalDatasets)
      .leftJoin(agentEvalTestCases, eq(agentEvalDatasets.id, agentEvalTestCases.datasetId))
      .groupBy(agentEvalDatasets.id);
    

    One-to-Many (Separate Queries)

    When you need a parent record with its children, use two queries instead of relational with::

    // ✅ Good: two simple queries
    const [dataset] = await this.db
      .select()
      .from(agentEvalDatasets)
      .where(eq(agentEvalDatasets.id, id))
      .limit(1);
    
    if (!dataset) return undefined;
    
    const testCases = await this.db
      .select()
      .from(agentEvalTestCases)
      .where(eq(agentEvalTestCases.datasetId, id))
      .orderBy(asc(agentEvalTestCases.sortOrder));
    
    return { ...dataset, testCases };
    

    Database Migrations

    See the db-migrations skill for the detailed migration guide.

    Recommended Servers
    Prisma
    Prisma
    Neon
    Neon
    Airtable
    Airtable
    Repository
    lobehub/lobehub
    Files