Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
pproenca avatar

Drizzle Sqlite Scaffold

  • 84 installs
  • 191 repo stars
  • Updated July 24, 2026
  • pproenca/dot-skills

drizzle-sqlite-scaffold is a Claude Code skill for databases. It helps solo builders move faster with AI-assisted coding.

Key points

  • drizzle-sqlite-scaffold
  • Databases
  • AI-coding skill

Drizzle Sqlite Scaffold by the numbers

  • 84 all-time installs (skills.sh)
  • +6 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #348 of 911 Databases skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pproenca/dot-skills --skill drizzle-sqlite-scaffold

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs84
repo stars191
Last updatedJuly 24, 2026
Repositorypproenca/dot-skills

How do I helps with databases tasks during ai-assisted development?

Helps with databases tasks during AI-assisted development.

Who is it for?

Best when you're working on databases and need structured help with drizzle-sqlite-scaffold.

Skip if: Teams with no databases needs, or anyone wanting a generic chat assistant without this specific workflow.

When should I use this skill?

When you need to helps with databases tasks during ai-assisted development, or when drizzle-sqlite-scaffold is a claude code skill for databases. it helps solo builders move faster with ai-assisted coding.

What you get

Structured output aligned to drizzle-sqlite-scaffold: drizzle-sqlite-scaffold; Databases; AI-coding skill.

Files

SKILL.mdMarkdownGitHub ↗

Drizzle SQLite Scaffold

Parameterized templates for bootstrapping Drizzle + SQLite in a fresh project, or adding a new table/repository to an existing one. Every output bakes in the conventions documented in `references/conventions.md` — explicit primary keys, indexed foreign keys, relations() declarations, $inferSelect/$inferInsert exports, timestamp_ms dates, boolean-mode bools, WAL + foreign_keys=ON + busy_timeout pragmas, singleton client with HMR guard, and CRUD helpers using .returning() + inArray() + .onConflictDoUpdate().

When to Apply

Reach for these templates when:

  • Starting a new project that will use Drizzle with SQLite (any driver)
  • Adding a new table to an existing Drizzle project — the table file should match the existing patterns
  • Adding a CRUD repository module for an existing table
  • Refactoring a hand-rolled Drizzle setup that's missing pragmas, has no relations(), or has hand-written User types that drift from the schema
  • Migrating from another ORM (Prisma, Kysely) to Drizzle and wanting consistent shapes from the start

Setup

Required parameters (asked on first use, saved to config.json)

ParameterRequiredDefaultValues
driveryesbetter-sqlite3 \
db_url_envnoDATABASE_URLenv var name
schema_dirno./src/db/schemaper-table schema files
repository_dirno./src/db/repositoryper-table CRUD modules
validators_dirno./src/db/validatorsdrizzle-zod schemas (when with_zod=true)
client_pathno./src/db/client.tssingleton client module
migrations_dirno./drizzledrizzle-kit output

If config.json already exists with values, this skill uses them; otherwise it asks via AskUserQuestion.

Per-table parameters (asked each time a new table is scaffolded)

ParameterRequiredDefaultDescription
nameyesKebab-case singular: user, order-item. Used for filenames and TS identifiers (name_camel, name_pascal derived).
table_namenosnake_case plural of nameSQL table name: users, order_items
pknoserial-intserial-int \
timestampsnotrueadds createdAt/updatedAt columns
soft_deletenofalseadds nullable deletedAt + partial index
relationsno[]list of related table names — expands relations() body
with_zodnotrueemits a drizzle-zod validators file

Available Templates

Project-init templates (emit once)

TemplateOutput FileWhen
`drizzle.config.local.ts.template`drizzle.config.tsdriver is better-sqlite3, bun-sqlite, or libsql with a file: URL
`drizzle.config.turso.ts.template`drizzle.config.tsdriver is libsql against Turso (remote libsql: URL)
`client.better-sqlite3.ts.template`{{client_path}}driver is better-sqlite3
`client.libsql.ts.template`{{client_path}}driver is libsql
`client.bun-sqlite.ts.template`{{client_path}}driver is bun-sqlite
`schema-index.ts.template`{{schema_dir}}/index.tsAlways (initially empty; append exports as tables are added)
`gitignore.template`.gitignore (append)Always

Per-table templates (emit once per table)

TemplateOutput FileWhen
`table.ts.template`{{schema_dir}}/{{name}}.tsPer table
`repository.ts.template`{{repository_dir}}/{{name}}.tsPer table
`validators.ts.template`{{validators_dir}}/{{name}}.tsPer table when with_zod=true

How to Use

Flow A — Initialize a new project (run once)

1. Resolve project parameters. Read config.json. For any required field that's empty, ask the user via AskUserQuestion (driver is the only strictly required one; the rest have sensible defaults).

2. Install runtime + tooling first so the rendered files type-check immediately:

   # Pick the driver-specific runtime package:
   npm install drizzle-orm @libsql/client      # for libsql
   npm install drizzle-orm better-sqlite3      # for better-sqlite3
   npm install drizzle-orm                     # bun:sqlite is built into Bun

   # Dev tools (all drivers):
   npm install -D drizzle-kit
   npm install -D @types/better-sqlite3        # better-sqlite3 only
   npm install -D drizzle-zod zod              # if with_zod=true

3. Pick the config and client variants for the resolved driver:

  • better-sqlite3drizzle.config.local.ts.template + client.better-sqlite3.ts.template
  • libsql with file: URL → drizzle.config.local.ts.template + client.libsql.ts.template
  • libsql with remote Turso URL → drizzle.config.turso.ts.template + client.libsql.ts.template
  • bun-sqlitedrizzle.config.local.ts.template + client.bun-sqlite.ts.template

4. Render and write the project-init files:

  • drizzle.config.ts
  • {{client_path}} (typically src/db/client.ts)
  • {{schema_dir}}/index.ts (empty barrel)
  • Append the gitignore.template block to the project's .gitignore

5. For libsql: the client template uses top-level await migrate(...). Verify tsconfig.json has "module": "ESNext" (or "NodeNext") and "target": "ES2022"+ for top-level await support. If the runtime is CommonJS, replace the top-level await with an exported async function init() the app calls during startup.

6. Save resolved values to `config.json` so subsequent table runs don't re-prompt.

Flow B — Add a new table (run per table)

1. Resolve per-table parameters. Ask the user for name, then offer defaults for table_name (snake_case plural), pk, timestamps, soft_delete, relations, with_zod. Use AskUserQuestion for any non-default the user wants.

2. Compute derived identifiers:

  • name_camel — camelCase of name (user, orderItem)
  • name_pascal — PascalCase of name (User, OrderItem)
  • pk_field — the PK column name (id for all 4 pk modes)
  • pk_ts_type — TS type for the PK (number for serial-int, string for uuid/cuid2/text)
  • pk_definition — the actual line, e.g., id: integer().primaryKey({ autoIncrement: true }), (see PK Variants table below)

3. Render the table template: Read table.ts.template, substitute {{name}}, {{name_camel}}, {{name_pascal}}, {{table_name}}, {{pk_definition}}, {{pk_extra_imports}}, etc. Expand {{timestamps_block}} and {{soft_delete_block}} per the parameters (see "Block Expansions" below). Write to {{schema_dir}}/{{name}}.ts.

4. Render the repository template with the same parameters. Write to {{repository_dir}}/{{name}}.ts.

5. If `with_zod=true`, render the validators template. Write to {{validators_dir}}/{{name}}.ts.

6. Append to the schema barrel: Add export * from './{{name}}'; to {{schema_dir}}/index.ts.

7. Generate the migration: Tell the user to run npx drizzle-kit generate to produce the SQL file. Remind them to answer rename prompts explicitly if this scaffold replaces an existing differently-named table.

8. Apply the migration: Run npx drizzle-kit migrate against the dev database. The client templates also call migrate(...) on boot, but applying once in the dev loop confirms the SQL works before the next process restart.

Flow C — Add a CRUD module for an existing table (no schema change)

Same as Flow B steps 1-2, but skip the table.ts.template render and just emit the repository (and optionally validators) modules.

PK Variants

pk valuepk_definitionpk_ts_typeExtra imports
serial-int (default)id: integer().primaryKey({ autoIncrement: true }),number
uuidid: text().primaryKey().$defaultFn(() => crypto.randomUUID()),string— (uses Web Crypto)
cuid2id: text().primaryKey().$defaultFn(() => createId()),stringimport { createId } from '@paralleldrive/cuid2';
textid: text().primaryKey(),string— (caller supplies the ID)

Placeholder Reference

Every {{placeholder}} the templates use, with its derivation rule. Items marked simple sub are find-and-replace; items marked block require the agent to expand per the rules in the next section.

PlaceholderTypeSource / derivation
{{driver}}simple subconfig.json:driver
{{db_url_env}}simple subconfig.json:db_url_env
{{schema_dir}}simple subconfig.json:schema_dir
{{repository_dir}}simple subconfig.json:repository_dir
{{validators_dir}}simple subconfig.json:validators_dir
{{client_path}}simple subconfig.json:client_path
{{migrations_dir}}simple subconfig.json:migrations_dir
{{schema_index_import}}simple subderived: client_path → relative path to {{schema_dir}}/index.ts (typically './schema')
{{client_import}}simple subderived: from a repository file, relative path back to client_path (typically '../client')
{{schema_import}}simple subderived: from a repository or validators file, relative path to the matching table file (typically '../schema/{{name}}')
{{name}}simple subper-table param — kebab-case singular (user)
{{name_camel}}simple subderived from name (user, orderItem)
{{name_pascal}}simple subderived from name (User, OrderItem)
{{table_name}}simple subper-table param, default = snake_case plural of name (users, order_items)
{{pk}}metadataper-table param — serial-int \
{{pk_definition}}blockthe actual PK column line — see "PK Variants" table
{{pk_field}}simple subalways id for the four PK variants this skill ships
{{pk_ts_type}}simple subnumber for serial-int, string for uuid / cuid2 / text
{{pk_extra_imports}}blockempty for serial-int / uuid / text; import { createId } from '@paralleldrive/cuid2'; for cuid2
{{relation_imports}}blockfor each table in relations[], emit import { {{relatedCamel}} } from './{{related-kebab}}';
{{domain_columns}}blockthe agent (or user) replaces this with the actual non-PK, non-timestamp columns for the entity. Leave as a TODO comment if the user hasn't provided them yet.
{{timestamps_block}}blocksee expansion below — emit when timestamps=true, remove the line entirely when false
{{soft_delete_block}}blocksee expansion below — emit in the columns block when soft_delete=true
{{indexes}}blockone index(...) line per foreign key column (and any composite (authorId, publishedAt)-style indexes the user wants)
{{soft_delete_index}}blockthe partial index on deletedAt (see expansion below); emit only when soft_delete=true
{{relations_body}}blockone one(...) / many(...) line per related table; see expansion below
{{insert_refinements}}blockdrizzle-zod refinement callbacks for the INSERT shape; leave the example comment if none provided
{{update_refinements}}blocksame for the partial UPDATE shape
{{exports}}blockinside schema-index.ts.template: one export * from './{{name}}'; line per table; append on each new-table run

If a template emits a {{placeholder}} not in this table, that's a bug — file it under gotchas.md.

Block Expansions

The table.ts.template uses placeholder blocks for variable-shaped sections — the agent must expand them per parameters, not just text-substitute.

{{timestamps_block}} (when timestamps=true)

createdAt: integer({ mode: 'timestamp_ms' })
  .notNull()
  .$defaultFn(() => new Date()),
updatedAt: integer({ mode: 'timestamp_ms' })
  .notNull()
  .$defaultFn(() => new Date())
  .$onUpdateFn(() => new Date()),

When timestamps=false, remove the line entirely (don't leave the comment marker).

{{soft_delete_block}} (when soft_delete=true)

In the columns block:

deletedAt: integer({ mode: 'timestamp_ms' }),

In the indexes block:

index('{{table_name}}_active_idx').on(table.deletedAt).where(sql`deleted_at IS NULL`),

(Adjust the sql import accordingly.)

{{relations_body}} (when relations is non-empty)

For each related table in relations[], the agent decides whether it's a one or many based on whether the FK lives on the current table (then it's one) or on the related table (then it's many):

// FK on current table — `one`:
parent: one(parents, { fields: [users.parentId], references: [parents.id] }),

// FK on related table — `many`:
posts: many(posts),

If the user can't easily tell, default to one example of each and leave a comment.

{{indexes}} block

For each FK column, emit:

index('{{table_name}}_{{column}}_idx').on(table.{{columnCamel}}),

Cloudflare D1 note

D1 has a different lifecycle: the client is constructed per request from env.DB (the binding), not as a module-level singleton. This skill doesn't ship a D1 client template — follow the official D1 + Drizzle guide for the wiring. The table.ts.template, repository.ts.template, and validators.ts.template are still usable with D1 — only the client module differs.

Reference Files

FileDescription
references/conventions.mdThe 11 conventions enforced, with WHY and rule cross-references
gotchas.mdEdge cases discovered over time
metadata.jsonVersion + driver references
config.jsonProject-level parameter store

Related Skills

  • [`drizzle-sqlite`](../drizzle-sqlite/SKILL.md) — The library-reference rules these templates encode. The conventions doc cites specific rule filenames from it. Read it when you need to make an informed exception, debug a generated file, or scaffold something outside the templates' scope (custom migrations, complex queries, performance work).
  • [`better-auth-scaffold`](../better-auth-scaffold/SKILL.md) — Scaffolds Better Auth on top of a Drizzle DB; can be run after this skill provides the client.

Related skills

FAQ

What does drizzle-sqlite-scaffold do?

drizzle-sqlite-scaffold is a Claude Code skill for databases. It helps developers move faster with AI-assisted coding.

When should I use drizzle-sqlite-scaffold?

When you need to helps with databases tasks during ai-assisted development, or when drizzle-sqlite-scaffold is a claude code skill for databases. it helps developers move faster with ai-assisted coding.

What are the main capabilities?

drizzle-sqlite-scaffold; Databases; AI-coding skill.

Databasesdatabases

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.