[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7BFAGCYXCJ6RTYCX2DB04MM":3,"skill-same:01M7BFAGCYXCJ6RTYCX2DB04MM":48},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":30,"ownerHtmlUrl":31,"ownerBlogUrl":6,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M7BFAGCYXCJ6RTYCX2DB04MM","database-migrations",null,"数据库迁移最佳实践，涵盖模式变更、数据迁移、回滚以及零停机部署，适用于PostgreSQL、MySQL及常用ORM（Prisma、Drizzle、Django、TypeORM、golang-migrate）。","YYC-Cube\u002FYYC3-Knowledge-Base","YYC-Cube","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F235006543?v=4","01M79J2PH4SWD2X0825X6PN748","yyc3","01M79J2PHVK3F6ZBYT8K2SCZCW",1,"MIT","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-AI-应用工具\u002FYYC3-AI-应用工具-Everything-claude-code\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdatabase-migrations\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: database-migrations\ndescription: 数据库迁移最佳实践，涵盖模式变更、数据迁移、回滚以及零停机部署，适用于PostgreSQL、MySQL及常用ORM（Prisma、Drizzle、Django、TypeORM、golang-migrate）。\norigin: ECC\n---\n\n# 数据库迁移模式\n\n为生产系统提供安全、可逆的数据库模式变更。\n\n## 何时激活\n\n* 创建或修改数据库表\n* 添加\u002F删除列或索引\n* 运行数据迁移（回填、转换）\n* 计划零停机模式变更\n* 为新项目设置迁移工具\n\n## 核心原则\n\n1. **每个变更都是一次迁移** — 切勿手动更改生产数据库\n2. **迁移在生产环境中是只进不退的** — 回滚使用新的前向迁移\n3. **模式迁移和数据迁移是分开的** — 切勿在一个迁移中混合 DDL 和 DML\n4. **针对生产规模的数据测试迁移** — 适用于 100 行的迁移可能在 1000 万行时锁定\n5. **迁移一旦部署就是不可变的** — 切勿编辑已在生产中运行的迁移\n\n## 迁移安全检查清单\n\n应用任何迁移之前：\n\n* \\[ ] 迁移同时包含 UP 和 DOWN（或明确标记为不可逆）\n* \\[ ] 对大表没有全表锁（使用并发操作）\n* \\[ ] 新列有默认值或可为空（切勿添加没有默认值的 NOT NULL）\n* \\[ ] 索引是并发创建的（对于现有表，不与 CREATE TABLE 内联创建）\n* \\[ ] 数据回填是与模式变更分开的迁移\n* \\[ ] 已针对生产数据副本进行测试\n* \\[ ] 回滚计划已记录\n\n## PostgreSQL 模式\n\n### 安全地添加列\n\n```sql\n-- GOOD: Nullable column, no lock\nALTER TABLE users ADD COLUMN avatar_url TEXT;\n\n-- GOOD: Column with default (Postgres 11+ is instant, no rewrite)\nALTER TABLE users ADD COLUMN is_active BOOLEAN NOT NULL DEFAULT true;\n\n-- BAD: NOT NULL without default on existing table (requires full rewrite)\nALTER TABLE users ADD COLUMN role TEXT NOT NULL;\n-- This locks the table and rewrites every row\n```\n\n### 无停机添加索引\n\n```sql\n-- BAD: Blocks writes on large tables\nCREATE INDEX idx_users_email ON users (email);\n\n-- GOOD: Non-blocking, allows concurrent writes\nCREATE INDEX CONCURRENTLY idx_users_email ON users (email);\n\n-- Note: CONCURRENTLY cannot run inside a transaction block\n-- Most migration tools need special handling for this\n```\n\n### 重命名列（零停机）\n\n切勿在生产中直接重命名。使用扩展-收缩模式：\n\n```sql\n-- Step 1: Add new column (migration 001)\nALTER TABLE users ADD COLUMN display_name TEXT;\n\n-- Step 2: Backfill data (migration 002, data migration)\nUPDATE users SET display_name = username WHERE display_name IS NULL;\n\n-- Step 3: Update application code to read\u002Fwrite both columns\n-- Deploy application changes\n\n-- Step 4: Stop writing to old column, drop it (migration 003)\nALTER TABLE users DROP COLUMN username;\n```\n\n### 安全地删除列\n\n```sql\n-- Step 1: Remove all application references to the column\n-- Step 2: Deploy application without the column reference\n-- Step 3: Drop column in next migration\nALTER TABLE orders DROP COLUMN legacy_status;\n\n-- For Django: use SeparateDatabaseAndState to remove from model\n-- without generating DROP COLUMN (then drop in next migration)\n```\n\n### 大型数据迁移\n\n```sql\n-- BAD: Updates all rows in one transaction (locks table)\nUPDATE users SET normalized_email = LOWER(email);\n\n-- GOOD: Batch update with progress\nDO $$\nDECLARE\n  batch_size INT := 10000;\n  rows_updated INT;\nBEGIN\n  LOOP\n    UPDATE users\n    SET normalized_email = LOWER(email)\n    WHERE id IN (\n      SELECT id FROM users\n      WHERE normalized_email IS NULL\n      LIMIT batch_size\n      FOR UPDATE SKIP LOCKED\n    );\n    GET DIAGNOSTICS rows_updated = ROW_COUNT;\n    RAISE NOTICE 'Updated % rows', rows_updated;\n    EXIT WHEN rows_updated = 0;\n    COMMIT;\n  END LOOP;\nEND $$;\n```\n\n## Prisma (TypeScript\u002FNode.js)\n\n### 工作流\n\n```bash\n# Create migration from schema changes\nnpx prisma migrate dev --name add_user_avatar\n\n# Apply pending migrations in production\nnpx prisma migrate deploy\n\n# Reset database (dev only)\nnpx prisma migrate reset\n\n# Generate client after schema changes\nnpx prisma generate\n```\n\n### 模式示例\n\n```prisma\nmodel User {\n  id        String   @id @default(cuid())\n  email     String   @unique\n  name      String?\n  avatarUrl String?  @map(\"avatar_url\")\n  createdAt DateTime @default(now()) @map(\"created_at\")\n  updatedAt DateTime @updatedAt @map(\"updated_at\")\n  orders    Order[]\n\n  @@map(\"users\")\n  @@index([email])\n}\n```\n\n### 自定义 SQL 迁移\n\n对于 Prisma 无法表达的操作（并发索引、数据回填）：\n\n```bash\n# Create empty migration, then edit the SQL manually\nnpx prisma migrate dev --create-only --name add_email_index\n```\n\n```sql\n-- migrations\u002F20240115_add_email_index\u002Fmigration.sql\n-- Prisma cannot generate CONCURRENTLY, so we write it manually\nCREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email);\n```\n\n## Drizzle (TypeScript\u002FNode.js)\n\n### 工作流\n\n```bash\n# Generate migration from schema changes\nnpx drizzle-kit generate\n\n# Apply migrations\nnpx drizzle-kit migrate\n\n# Push schema directly (dev only, no migration file)\nnpx drizzle-kit push\n```\n\n### 模式示例\n\n```typescript\nimport { pgTable, text, timestamp, uuid, boolean } from \"drizzle-orm\u002Fpg-core\";\n\nexport const users = pgTable(\"users\", {\n  id: uuid(\"id\").primaryKey().defaultRandom(),\n  email: text(\"email\").notNull().unique(),\n  name: text(\"name\"),\n  isActive: boolean(\"is_active\").notNull().default(true),\n  createdAt: timestamp(\"created_at\").notNull().defaultNow(),\n  updatedAt: timestamp(\"updated_at\").notNull().defaultNow(),\n});\n```\n\n## Django (Python)\n\n### 工作流\n\n```bash\n# Generate migration from model changes\npython manage.py makemigrations\n\n# Apply migrations\npython manage.py migrate\n\n# Show migration status\npython manage.py showmigrations\n\n# Generate empty migration for custom SQL\npython manage.py makemigrations --empty app_name -n description\n```\n\n### 数据迁移\n\n```python\nfrom django.db import migrations\n\ndef backfill_display_names(apps, schema_editor):\n    User = apps.get_model(\"accounts\", \"User\")\n    batch_size = 5000\n    users = User.objects.filter(display_name=\"\")\n    while users.exists():\n        batch = list(users[:batch_size])\n        for user in batch:\n            user.display_name = user.username\n        User.objects.bulk_update(batch, [\"display_name\"], batch_size=batch_size)\n\ndef reverse_backfill(apps, schema_editor):\n    pass  # Data migration, no reverse needed\n\nclass Migration(migrations.Migration):\n    dependencies = [(\"accounts\", \"0015_add_display_name\")]\n\n    operations = [\n        migrations.RunPython(backfill_display_names, reverse_backfill),\n    ]\n```\n\n### SeparateDatabaseAndState\n\n从 Django 模型中删除列，而不立即从数据库中删除：\n\n```python\nclass Migration(migrations.Migration):\n    operations = [\n        migrations.SeparateDatabaseAndState(\n            state_operations=[\n                migrations.RemoveField(model_name=\"user\", name=\"legacy_field\"),\n            ],\n            database_operations=[],  # Don't touch the DB yet\n        ),\n    ]\n```\n\n## golang-migrate (Go)\n\n### 工作流\n\n```bash\n# Create migration pair\nmigrate create -ext sql -dir migrations -seq add_user_avatar\n\n# Apply all pending migrations\nmigrate -path migrations -database \"$DATABASE_URL\" up\n\n# Rollback last migration\nmigrate -path migrations -database \"$DATABASE_URL\" down 1\n\n# Force version (fix dirty state)\nmigrate -path migrations -database \"$DATABASE_URL\" force VERSION\n```\n\n### 迁移文件\n\n```sql\n-- migrations\u002F000003_add_user_avatar.up.sql\nALTER TABLE users ADD COLUMN avatar_url TEXT;\nCREATE INDEX CONCURRENTLY idx_users_avatar ON users (avatar_url) WHERE avatar_url IS NOT NULL;\n\n-- migrations\u002F000003_add_user_avatar.down.sql\nDROP INDEX IF EXISTS idx_users_avatar;\nALTER TABLE users DROP COLUMN IF EXISTS avatar_url;\n```\n\n## 零停机迁移策略\n\n对于关键的生产变更，遵循扩展-收缩模式：\n\n```\nPhase 1: EXPAND\n  - 添加新列\u002F表（可为空或带有默认值）\n  - 部署：应用同时写入旧数据和新数据\n  - 回填现有数据\n\nPhase 2: MIGRATE\n  - 部署：应用读取新数据，同时写入新旧数据\n  - 验证数据一致性\n\nPhase 3: CONTRACT\n  - 部署：应用仅使用新数据\n  - 在单独迁移中删除旧列\u002F表\n```\n\n### 时间线示例\n\n```\nDay 1：迁移添加新的 `new_status` 列（可空）\nDay 1：部署应用 v2 —— 同时写入 `status` 和 `new_status`\nDay 2：运行针对现有行的回填迁移\nDay 3：部署应用 v3 —— 仅从 `new_status` 读取\nDay 7：迁移删除旧的 `status` 列\n```\n\n## 反模式\n\n| 反模式 | 为何会失败 | 更好的方法 |\n|-------------|-------------|-----------------|\n| 在生产中手动执行 SQL | 没有审计追踪，不可重复 | 始终使用迁移文件 |\n| 编辑已部署的迁移 | 导致环境间出现差异 | 改为创建新迁移 |\n| 没有默认值的 NOT NULL | 锁定表，重写所有行 | 添加可为空列，回填数据，然后添加约束 |\n| 在大表上内联创建索引 | 在构建期间阻塞写入 | 使用 CREATE INDEX CONCURRENTLY |\n| 在一个迁移中混合模式和数据的变更 | 难以回滚，事务时间长 | 分开的迁移 |\n| 在移除代码之前删除列 | 应用程序在缺失列时出错 | 先移除代码，下一次部署再删除列 |\n","# 数据库迁移模式\n\n为生产系统提供安全、可逆的数据库模式变更。\n\n## 何时激活\n\n* 创建或修改数据库表\n* 添加\u002F删除列或索引\n* 运行数据迁移（回填、转换）\n* 计划零停机模式变更\n* 为新项目设置迁移工具\n\n## 核心原则\n\n1. **每个变更都是一次迁移** — 切勿手动更改生产数据库\n2. **迁移在生产环境中是只进不退的** — 回滚使用新的前向迁移\n3. **模式迁移和数据迁移是分开的** — 切勿在一个迁移中混合 DDL 和 DML\n4. **针对生产规模的数据测试迁移** — 适用于 100 行的迁移可能在 1000 万行时锁定\n5. **迁移一旦部署就是不可变的** — 切勿编辑已在生产中运行的迁移\n\n## 迁移安全检查清单\n\n应用任何迁移之前：\n\n* \\[ ] 迁移同时包含 UP 和 DOWN（或明确标记为不可逆）\n* \\[ ] 对大表没有全表锁（使用并发操作）\n* \\[ ] 新列有默认值或可为空（切勿添加没有默认值的 NOT NULL）\n* \\[ ] 索引是并发创建的（对于现有表，不与 CREATE TABLE 内联创建）\n* \\[ ] 数据回填是与模式变更分开的迁移\n* \\[ ] 已针对生产数据副本进行测试\n* \\[ ] 回滚计划已记录\n\n## PostgreSQL 模式\n\n### 安全地添加列\n\n```sql\n-- GOOD: Nullable column, no lock\nALTER TABLE users ADD COLUMN avatar_url TEXT;\n\n-- GOOD: Column with default (Postgres 11+ is instant, no rewrite)\nALTER TABLE users ADD COLUMN is_active BOOLEAN NOT NULL DEFAULT true;\n\n-- BAD: NOT NULL without default on existing table (requires full rewrite)\nALTER TABLE users ADD COLUMN role TEXT NOT NULL;\n-- This locks the table and rewrites every row\n```\n\n### 无停机添加索引\n\n```sql\n-- BAD: Blocks writes on large tables\nCREATE INDEX idx_users_email ON users (email);\n\n-- GOOD: Non-blocking, allows concurrent writes\nCREATE INDEX CONCURRENTLY idx_users_email ON users (email);\n\n-- Note: CONCURRENTLY cannot run inside a transaction block\n-- Most migration tools need special handling for this\n```\n\n### 重命名列（零停机）\n\n切勿在生产中直接重命名。使用扩展-收缩模式：\n\n```sql\n-- Step 1: Add new column (migration 001)\nALTER TABLE users ADD COLUMN display_name TEXT;\n\n-- Step 2: Backfill data (migration 002, data migration)\nUPDATE users SET display_name = username WHERE display_name IS NULL;\n\n-- Step 3: Update application code to read\u002Fwrite both columns\n-- Deploy application changes\n\n-- Step 4: Stop writing to old column, drop it (migration 003)\nALTER TABLE users DROP COLUMN username;\n```\n\n### 安全地删除列\n\n```sql\n-- Step 1: Remove all application references to the column\n-- Step 2: Deploy application without the column reference\n-- Step 3: Drop column in next migration\nALTER TABLE orders DROP COLUMN legacy_status;\n\n-- For Django: use SeparateDatabaseAndState to remove from model\n-- without generating DROP COLUMN (then drop in next migration)\n```\n\n### 大型数据迁移\n\n```sql\n-- BAD: Updates all rows in one transaction (locks table)\nUPDATE users SET normalized_email = LOWER(email);\n\n-- GOOD: Batch update with progress\nDO $$\nDECLARE\n  batch_size INT := 10000;\n  rows_updated INT;\nBEGIN\n  LOOP\n    UPDATE users\n    SET normalized_email = LOWER(email)\n    WHERE id IN (\n      SELECT id FROM users\n      WHERE normalized_email IS NULL\n      LIMIT batch_size\n      FOR UPDATE SKIP LOCKED\n    );\n    GET DIAGNOSTICS rows_updated = ROW_COUNT;\n    RAISE NOTICE 'Updated % rows', rows_updated;\n    EXIT WHEN rows_updated = 0;\n    COMMIT;\n  END LOOP;\nEND $$;\n```\n\n## Prisma (TypeScript\u002FNode.js)\n\n### 工作流\n\n```bash\n# Create migration from schema changes\nnpx prisma migrate dev --name add_user_avatar\n\n# Apply pending migrations in production\nnpx prisma migrate deploy\n\n# Reset database (dev only)\nnpx prisma migrate reset\n\n# Generate client after schema changes\nnpx prisma generate\n```\n\n### 模式示例\n\n```prisma\nmodel User {\n  id        String   @id @default(cuid())\n  email     String   @unique\n  name      String?\n  avatarUrl String?  @map(\"avatar_url\")\n  createdAt DateTime @default(now()) @map(\"created_at\")\n  updatedAt DateTime @updatedAt @map(\"updated_at\")\n  orders    Order[]\n\n  @@map(\"users\")\n  @@index([email])\n}\n```\n\n### 自定义 SQL 迁移\n\n对于 Prisma 无法表达的操作（并发索引、数据回填）：\n\n```bash\n# Create empty migration, then edit the SQL manually\nnpx prisma migrate dev --create-only --name add_email_index\n```\n\n```sql\n-- migrations\u002F20240115_add_email_index\u002Fmigration.sql\n-- Prisma cannot generate CONCURRENTLY, so we write it manually\nCREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users (email);\n```\n\n## Drizzle (TypeScript\u002FNode.js)\n\n### 工作流\n\n```bash\n# Generate migration from schema changes\nnpx drizzle-kit generate\n\n# Apply migrations\nnpx drizzle-kit migrate\n\n# Push schema directly (dev only, no migration file)\nnpx drizzle-kit push\n```\n\n### 模式示例\n\n```typescript\nimport { pgTable, text, timestamp, uuid, boolean } from \"drizzle-orm\u002Fpg-core\";\n\nexport const users = pgTable(\"users\", {\n  id: uuid(\"id\").primaryKey().defaultRandom(),\n  email: text(\"email\").notNull().unique(),\n  name: text(\"name\"),\n  isActive: boolean(\"is_active\").notNull().default(true),\n  createdAt: timestamp(\"created_at\").notNull().defaultNow(),\n  updatedAt: timestamp(\"updated_at\").notNull().defaultNow(),\n});\n```\n\n## Django (Python)\n\n### 工作流\n\n```bash\n# Generate migration from model changes\npython manage.py makemigrations\n\n# Apply migrations\npython manage.py migrate\n\n# Show migration status\npython manage.py showmigrations\n\n# Generate empty migration for custom SQL\npython manage.py makemigrations --empty app_name -n description\n```\n\n### 数据迁移\n\n```python\nfrom django.db import migrations\n\ndef backfill_display_names(apps, schema_editor):\n    User = apps.get_model(\"accounts\", \"User\")\n    batch_size = 5000\n    users = User.objects.filter(display_name=\"\")\n    while users.exists():\n        batch = list(users[:batch_size])\n        for user in batch:\n            user.display_name = user.username\n        User.objects.bulk_update(batch, [\"display_name\"], batch_size=batch_size)\n\ndef reverse_backfill(apps, schema_editor):\n    pass  # Data migration, no reverse needed\n\nclass Migration(migrations.Migration):\n    dependencies = [(\"accounts\", \"0015_add_display_name\")]\n\n    operations = [\n        migrations.RunPython(backfill_display_names, reverse_backfill),\n    ]\n```\n\n### SeparateDatabaseAndState\n\n从 Django 模型中删除列，而不立即从数据库中删除：\n\n```python\nclass Migration(migrations.Migration):\n    operations = [\n        migrations.SeparateDatabaseAndState(\n            state_operations=[\n                migrations.RemoveField(model_name=\"user\", name=\"legacy_field\"),\n            ],\n            database_operations=[],  # Don't touch the DB yet\n        ),\n    ]\n```\n\n## golang-migrate (Go)\n\n### 工作流\n\n```bash\n# Create migration pair\nmigrate create -ext sql -dir migrations -seq add_user_avatar\n\n# Apply all pending migrations\nmigrate -path migrations -database \"$DATABASE_URL\" up\n\n# Rollback last migration\nmigrate -path migrations -database \"$DATABASE_URL\" down 1\n\n# Force version (fix dirty state)\nmigrate -path migrations -database \"$DATABASE_URL\" force VERSION\n```\n\n### 迁移文件\n\n```sql\n-- migrations\u002F000003_add_user_avatar.up.sql\nALTER TABLE users ADD COLUMN avatar_url TEXT;\nCREATE INDEX CONCURRENTLY idx_users_avatar ON users (avatar_url) WHERE avatar_url IS NOT NULL;\n\n-- migrations\u002F000003_add_user_avatar.down.sql\nDROP INDEX IF EXISTS idx_users_avatar;\nALTER TABLE users DROP COLUMN IF EXISTS avatar_url;\n```\n\n## 零停机迁移策略\n\n对于关键的生产变更，遵循扩展-收缩模式：\n\n```\nPhase 1: EXPAND\n  - 添加新列\u002F表（可为空或带有默认值）\n  - 部署：应用同时写入旧数据和新数据\n  - 回填现有数据\n\nPhase 2: MIGRATE\n  - 部署：应用读取新数据，同时写入新旧数据\n  - 验证数据一致性\n\nPhase 3: CONTRACT\n  - 部署：应用仅使用新数据\n  - 在单独迁移中删除旧列\u002F表\n```\n\n### 时间线示例\n\n```\nDay 1：迁移添加新的 `new_status` 列（可空）\nDay 1：部署应用 v2 —— 同时写入 `status` 和 `new_status`\nDay 2：运行针对现有行的回填迁移\nDay 3：部署应用 v3 —— 仅从 `new_status` 读取\nDay 7：迁移删除旧的 `status` 列\n```\n\n## 反模式\n\n| 反模式 | 为何会失败 | 更好的方法 |\n|-------------|-------------|-----------------|\n| 在生产中手动执行 SQL | 没有审计追踪，不可重复 | 始终使用迁移文件 |\n| 编辑已部署的迁移 | 导致环境间出现差异 | 改为创建新迁移 |\n| 没有默认值的 NOT NULL | 锁定表，重写所有行 | 添加可为空列，回填数据，然后添加约束 |\n| 在大表上内联创建索引 | 在构建期间阻塞写入 | 使用 CREATE INDEX CONCURRENTLY |\n| 在一个迁移中混合模式和数据的变更 | 难以回滚，事务时间长 | 分开的迁移 |\n| 在移除代码之前删除列 | 应用程序在缺失列时出错 | 先移除代码，下一次部署再删除列 |\n",{"name":5,"origin":24,"description":7},"ECC","main","87afe6ce96220accf50a345dea46784c8c9f210e","YYC3-AI-应用工具\u002FYYC3-AI-应用工具-Everything-claude-code\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdatabase-migrations",0,"https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base","https:\u002F\u002Fkb.yyc3.top\u002F","https:\u002F\u002Fgithub.com\u002FYYC-Cube","万象归元于云枢 | 深栈智启新纪元","2026-11-10 10:37:32",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add YYC-Cube\u002FYYC3-Knowledge-Base --skill database-migrations",{"tool":40,"command":41},"bunx","bunx skills add YYC-Cube\u002FYYC3-Knowledge-Base --skill database-migrations",{"tool":43,"command":44},"pnpm","pnpm dlx skills add YYC-Cube\u002FYYC3-Knowledge-Base --skill database-migrations","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-AI-应用工具\u002FYYC3-AI-应用工具-Everything-claude-code\u002Fdocs\u002Fzh-CN\u002Fskills\u002Fdatabase-migrations\u002FSKILL.md",true,[],[49,56,63,70,77,84],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":53,"categories":54,"keywords":55,"publishedAt":19},"01M7CTDWHERCXPQCP0K03A86AS","vercel-sandbox","Run agent-browser + Chrome inside Vercel Sandbox microVMs for browser automation from any Vercel-deployed app. Use when the user needs browser automation in a Vercel app (Next.js, SvelteKit, Nuxt, Remix, Astro, etc.), wants to run headless Chrome without binary size limits, needs persistent browser sessions across commands, or wants ephemeral isolated browser environments. Triggers include \"Vercel Sandbox browser\", \"microVM Chrome\", \"agent-browser in sandbox\", \"browser automation on Vercel\", or any task requiring Chrome in a Vercel Sandbox.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-WebSpec-Web标准\u002FYYC3-WebSpec-Web标准-standards\u002Fbrowser-agent\u002Fskills\u002Fvercel-sandbox\u002FSKILL.md",[],[],{"skillNo":57,"name":58,"nameZh":6,"description":59,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":60,"categories":61,"keywords":62,"publishedAt":19},"01M7CTD8D2BNJY54S65M47HEJA","slack","Interact with Slack workspaces using browser automation. Use when the user needs to check unread channels, navigate Slack, send messages, extract data, find information, search conversations, or automate any Slack task. Triggers include \"check my Slack\", \"what channels have unreads\", \"send a message to\", \"search Slack for\", \"extract from Slack\", \"find who said\", or any task requiring programmatic Slack interaction.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-WebSpec-Web标准\u002FYYC3-WebSpec-Web标准-standards\u002Fbrowser-agent\u002Fskills\u002Fslack\u002FSKILL.md",[],[],{"skillNo":64,"name":65,"nameZh":6,"description":66,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":67,"categories":68,"keywords":69,"publishedAt":19},"01M7CTCSSB8ZP3Q58C3YZDZK1W","electron","Automate Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify, etc.) using agent-browser via Chrome DevTools Protocol. Use when the user needs to interact with an Electron app, automate a desktop app, connect to a running app, control a native app, or test an Electron application. Triggers include \"automate Slack app\", \"control VS Code\", \"interact with Discord app\", \"test this Electron app\", \"connect to desktop app\", or any task requiring automation of a native Electron application.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-WebSpec-Web标准\u002FYYC3-WebSpec-Web标准-standards\u002Fbrowser-agent\u002Fskills\u002Felectron\u002FSKILL.md",[],[],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M7CTCBJY76688V4DCZGWFHGQ","dogfood","Systematically explore and test a web application to find bugs, UX issues, and other problems. Use when asked to \"dogfood\", \"QA\", \"exploratory test\", \"find issues\", \"bug hunt\", \"test this app\u002Fsite\u002Fplatform\", or review the quality of a web application. Produces a structured report with full reproduction evidence -- step-by-step screenshots, repro videos, and detailed repro steps for every issue -- so findings can be handed directly to the responsible teams.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-WebSpec-Web标准\u002FYYC3-WebSpec-Web标准-standards\u002Fbrowser-agent\u002Fskills\u002Fdogfood\u002FSKILL.md",[],[],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":19},"01M7CTC4H0FFGVEAQR9PA4GA1A","agent-browser","Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to \"open a website\", \"fill out a form\", \"click a button\", \"take a screenshot\", \"scrape data from a page\", \"test this web app\", \"login to a site\", \"automate browser actions\", or any task requiring programmatic web interaction.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-WebSpec-Web标准\u002FYYC3-WebSpec-Web标准-standards\u002Fbrowser-agent\u002Fskills\u002Fagent-browser\u002FSKILL.md",[],[],{"skillNo":85,"name":86,"nameZh":6,"description":87,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":19},"01M7CTBKVFYBG78FDSABSDJTTQ","shadcn","Manages shadcn components and projects — adding, searching, fixing, debugging, styling, and composing UI, including chat interfaces. Provides project context, component docs, and usage examples. Applies when working with shadcn\u002Fui, component registries, presets, --preset codes, or any project with a components.json file. Also triggers for \"shadcn init\", \"create an app with --preset\", \"switch to --preset\", and for building a design system or applying a DESIGN.md or brand spec to shadcn\u002Fui.","https:\u002F\u002Fgithub.com\u002FYYC-Cube\u002FYYC3-Knowledge-Base\u002Fblob\u002Fmain\u002FYYC3-UI-界面组件\u002FYYC3-UI-界面组件-ui\u002Fskills\u002Fshadcn\u002FSKILL.md",[],[]]