d1-migration — скилл для Claude Code: миграции Cloudflare D1
Ведёт миграции Cloudflare D1 через Drizzle: генерация SQL, проверка на опасные места, применение к локальной и удалённой базе, починка зависших миграций.
npx skills add jezweb/claude-skills --skill d1-migration -a claude-codeЧто делает d1-migration
Скилл описывает порядок работы с миграциями D1. Сначала pnpm db:generate создаёт новый .sql в drizzle/, потом файл нужно прочитать глазами. Drizzle иногда разворачивает простое изменение схемы в пересоздание таблицы: CREATE TABLE my_table_new, INSERT INTO ... SELECT с новой колонкой из старой таблицы, DROP TABLE, RENAME. Такой INSERT падает, потому что колонки в старой таблице ещё нет. Если вы только добавляете колонки, файл правят вручную до ALTER TABLE my_table ADD COLUMN. Это повод не запускать db:migrate вслепую.
Дальше миграция идёт в обе базы: pnpm db:migrate:local и pnpm db:migrate:remote. Только локально применять не стоит, иначе получите «локально работает, в продакшене ломается». Проверка — через npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)" и то же с --remote.
Отдельный раздел — зависшие миграции. Если колонка уже добавилась, а запись в d1_migrations не появилась, wrangler повторяет миграцию и спотыкается о дубликат. Лечится ручной вставкой строки в d1_migrations и обычным прогоном остатка. Ещё скилл напоминает про лимит параметров D1: большие multi-row INSERT падают молча, поэтому вставку режут на порции по 10 строк. Для нового проекта порядок другой: сначала деплой воркера, потом npx wrangler d1 create, перенос database_id в wrangler.jsonc, повторный деплой и миграции.
Какие задачи решает
- сгенерировать SQL-миграцию из схемы Drizzle
- поймать пересоздание таблицы в сгенерированном SQL до применения
- применить миграцию к локальной и удалённой базе D1
- починить миграцию, которая применилась частично и застряла
- разбить большой INSERT на порции из-за лимита параметров D1
Примеры запросов агенту
- сгенерируй миграцию и покажи SQL, прежде чем применять
- миграция застряла: колонка есть, а в d1_migrations записи нет — разберись
- настрой D1 для нового проекта и прогони миграции локально и удалённо
Как установить d1-migration
1Через Skills CLI (Vercel)
npx skills add jezweb/claude-skills --skill d1-migration -a claude-code2Вручную: положить файлы
~/.claude/skills/d1-migration/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/d1-migration/
1Через Skills CLI (Vercel)
npx skills add jezweb/claude-skills --skill d1-migration -a codex2Вручную: положить файлы
.agents/skills/d1-migration/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add jezweb/claude-skills --skill d1-migration -a cursor2Вручную: положить файлы
.cursor/skills/d1-migration/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install jezweb/claude-skills d1-migration2Вручную: положить файлы
.github/skills/d1-migration/SKILL.md1Через Skills CLI (Vercel)
npx skills add jezweb/claude-skills --skill d1-migration -a gemini-cli2Командой платформы
gemini skills install https://github.com/jezweb/claude-skills --path archive/plugins/cloudflare/skills/d1-migrationВручную: положить файлы
.devin/skills/d1-migration/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add jezweb/claude-skills --skill d1-migration -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Из того же набора54
Похожие
Рядом в теме «Данные и базы»
Все скиллы по теме «Данные и базы» →Вопросы о d1-migration
Как установить d1-migration в Claude?
Выполните npx skills add jezweb/claude-skills --skill d1-migration -a claude-code. Скилл встанет в ~/.claude/skills/d1-migration/SKILL.md.
Что делает d1-migration?
Проводит по шагам миграции Cloudflare D1 с Drizzle ORM: генерация, чтение SQL, применение к локальной и удалённой базе, проверка через wrangler d1 execute.
Почему миграция D1 зависает и как это исправить?
Колонка добавилась, но запись в d1_migrations не появилась, и wrangler падает на дубликате. Нужно вручную вставить строку в d1_migrations и прогнать оставшиеся миграции.
Исходный текст
SKILL.md · MIT
---
name: d1-migration
description: "Cloudflare D1 migration workflow: generate with Drizzle, inspect SQL for gotchas, apply to local and remote, fix stuck migrations, handle partial failures. Use when running migrations, fixing migration errors, or setting up D1 schemas."
compatibility: claude-code-only
---
# D1 Migration Workflow
Guided workflow for Cloudflare D1 database migrations using Drizzle ORM.
## Standard Migration Flow
### 1. Generate Migration
```bash
pnpm db:generate
```
This creates a new `.sql` file in `drizzle/` (or your configured migrations directory).
### 2. Inspect the SQL (CRITICAL)
**Always read the generated SQL before applying.** Drizzle sometimes generates destructive migrations for simple schema changes.
#### Red Flag: Table Recreation
If you see this pattern, the migration will likely fail:
```sql
CREATE TABLE `my_table_new` (...);
INSERT INTO `my_table_new` SELECT ..., `new_column`, ... FROM `my_table`;
-- ^^^ This column doesn't exist in old table!
DROP TABLE `my_table`;
ALTER TABLE `my_table_new` RENAME TO `my_table`;
```
**Cause**: Changing a column's `default` value in Drizzle schema triggers full table recreation. The INSERT SELECT references the new column from the old table.
**Fix**: If you're only adding new columns (no type/constraint changes on existing columns), simplify to:
```sql
ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';
```
Edit the `.sql` file directly before applying.
### 3. Apply to Local
```bash
pnpm db:migrate:local
# or: npx wrangler d1 migrations apply DB_NAME --local
```
### 4. Apply to Remote
```bash
pnpm db:migrate:remote
# or: npx wrangler d1 migrations apply DB_NAME --remote
```
**Always apply to BOTH local and remote before testing.** Local-only migrations cause confusing "works locally, breaks in production" issues.
### 5. Verify
```bash
# Check local
npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)"
# Check remote
npx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"
```
## Fixing Stuck Migrations
When a migration partially applied (e.g. column was added but migration wasn't recorded), wrangler retries it and fails on the duplicate column.
**Symptoms**: `pnpm db:migrate` errors on a migration that looks like it should be done. `PRAGMA table_info` shows the column exists.
### Diagnosis
```bash
# 1. Verify the column/table exists
npx wrangler d1 execute DB_NAME --remote \
--command "PRAGMA table_info(my_table)"
# 2. Check what migrations are recorded
npx wrangler d1 execute DB_NAME --remote \
--command "SELECT * FROM d1_migrations ORDER BY id"
```
### Fix
```bash
# 3. Manually record the stuck migration
npx wrangler d1 execute DB_NAME --remote \
--command "INSERT INTO d1_migrations (name, applied_at) VALUES ('0013_my_migration.sql', datetime('now'))"
# 4. Run remaining migrations normally
pnpm db:migrate
```
### Prevention
- `CREATE TABLE IF NOT EXISTS` — safe to re-run
- `ALTER TABLE ADD COLUMN` — SQLite has no `IF NOT EXISTS` variant; check column existence first or use try/catch in application code
- **Always inspect generated SQL** before applying (Step 2 above)
## Bulk Insert Batching
D1's parameter limit causes silent failures with large multi-row INSERTs. Batch into chunks:
```typescript
const BATCH_SIZE = 10;
for (let i = 0; i < allRows.length; i += BATCH_SIZE) {
const batch = allRows.slice(i, i + BATCH_SIZE);
await db.insert(myTable).values(batch);
}
```
**Why**: D1 fails when rows x columns exceeds ~100-150 parameters.
## Column Naming
| Context | Convention | Example |
|---------|-----------|---------|
| Drizzle schema | camelCase | `caseNumber: text('case_number')` |
| Raw SQL queries | snake_case | `UPDATE cases SET case_number = ?` |
| API responses | Match SQL aliases | `SELECT case_number FROM cases` |
## New Project Setup
When creating a D1 database for a new project, follow this order:
1. **Deploy Worker first** — `npm run build && npx wrangler deploy`
2. **Create D1 database** — `npx wrangler d1 create project-name-db`
3. **Copy database_id** to `wrangler.jsonc` `d1_databases` binding
4. **Redeploy** — `npx wrangler deploy`
5. **Run migrations** — apply to both local and remote
© jezweb · MIT · jezweb/claude-skills