migrate
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMigrate
迁移
Orchestrates monorepo migrations: import path changes, package renames, module moves. Uses scripted bulk operations (never file-by-file edits), deduplicates against existing work, verifies types at each step, and commits atomically.
编排Monorepo迁移:导入路径修改、包重命名、模块移动。采用脚本化批量操作(绝不逐文件编辑),与已有工作去重,在每个步骤验证类型,并以原子方式提交。
Load this skill when
加载此Skill的场景
- the same import or package rename must be applied across many files
- the task includes module moves plus path updates
- verification and atomic commits matter more than hand-editing a few files
- 同一导入或包重命名需要应用于多个文件时
- 任务包含模块移动及路径更新时
- 验证和原子提交比手动编辑少量文件更重要时
Scripts
脚本
Prefer the packaged helpers for manifest building and bulk replacement:
bash
bash scripts/build-manifest.sh @old/pkg/name
bash scripts/replace-imports.sh @old/pkg/name @new/pkg/name /tmp/migration-manifest.txt优先使用打包的辅助工具来构建清单和批量替换:
bash
bash scripts/build-manifest.sh @old/pkg/name
bash scripts/replace-imports.sh @old/pkg/name @new/pkg/name /tmp/migration-manifest.txtDo NOT load this skill when
请勿加载此Skill的场景
- the change only touches one or two files
- the user wants exploratory refactoring instead of a defined migration
- the package boundary decision itself is still unresolved
- 更改仅涉及一两个文件时
- 用户需要探索性重构而非明确的迁移时
- 包边界决策本身仍未确定时
Pipeline
流程
Step 1: Deduplication Check (always first)
步骤1:去重检查(始终第一步)
Before writing a single line, check if this migration was already done:
bash
git log --oneline -20
grep -r "<new-import-path>" apps/ packages/ --include="*.ts" --include="*.svelte" -l | head -10If the migration is already complete (or partially done), report what exists and ask the user whether to verify/clean up or skip.
在编写任何代码之前,检查此迁移是否已完成:
bash
git log --oneline -20
grep -r "<new-import-path>" apps/ packages/ --include="*.ts" --include="*.svelte" -l | head -10如果迁移已完成(或部分完成),报告现有情况并询问用户是要验证/清理还是跳过。
Step 2: Build Migration Manifest
步骤2:构建迁移清单
Produce a complete inventory before touching any files:
bash
undefined在修改任何文件之前生成完整的清单:
bash
undefinedFind all files needing migration
查找所有需要迁移的文件
grep -rl "<old-import-path>" apps/ packages/ --include=".ts" --include=".tsx" --include="*.svelte" > /tmp/migration-manifest.txt
echo "Files to migrate: $(wc -l < /tmp/migration-manifest.txt)"
cat /tmp/migration-manifest.txt
Group files by workspace for parallel execution planning:
- `apps/api/` — backend
- `apps/frontend/` — frontend + SvelteKit
- `packages/` — shared libraries
Print summary:
Migration: @portal/shared/server/auth → @portal/server/auth
apps/api: 12 files
apps/frontend: 8 files
packages/server: 3 files
Total: 23 files
Ask the user to confirm before proceeding if total > 20 files or if the change touches `packages/server` or `packages/types` (shared across workspaces).grep -rl "<old-import-path>" apps/ packages/ --include=".ts" --include=".tsx" --include="*.svelte" > /tmp/migration-manifest.txt
echo "Files to migrate: $(wc -l < /tmp/migration-manifest.txt)"
cat /tmp/migration-manifest.txt
按工作区分组文件以规划并行执行:
- `apps/api/` — 后端
- `apps/frontend/` — 前端 + SvelteKit
- `packages/` — 共享库
打印摘要:
Migration: @portal/shared/server/auth → @portal/server/auth
apps/api: 12 files
apps/frontend: 8 files
packages/server: 3 files
Total: 23 files
如果文件总数超过20个,或者更改涉及`packages/server`或`packages/types`(跨工作区共享),请在继续前征得用户确认。Step 3: Scripted Bulk Replacement
步骤3:脚本化批量替换
Use for each workspace (NOT file-by-file Edit calls):
sed -ibash
undefined对每个工作区使用(绝不使用逐文件编辑调用):
sed -ibash
undefinedAPI workspace
API工作区
grep -rl "@portal/shared/server/auth" apps/api/ --include="*.ts" |
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
grep -rl "@portal/shared/server/auth" apps/api/ --include="*.ts" |
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
Frontend workspace
前端工作区
grep -rl "@portal/shared/server/auth" apps/frontend/ --include=".ts" --include=".svelte" |
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
Note: macOS `sed` requires `sed -i ''` (empty string for in-place edit without backup).grep -rl "@portal/shared/server/auth" apps/frontend/ --include=".ts" --include=".svelte" |
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
xargs sed -i '' "s|@portal/shared/server/auth|@portal/server/auth|g"
注意:macOS的`sed`需要使用`sed -i ''`(空字符串表示无备份的原地编辑)。Step 4: Verification Gate
步骤4:验证关卡
After bulk replacement, verify each workspace compiles:
bash
undefined批量替换后,验证每个工作区是否可编译:
bash
undefinedAPI typecheck
API类型检查
cd apps/api && npx tsc --noEmit 2>&1 | head -30
cd apps/api && npx tsc --noEmit 2>&1 | head -30
Frontend typecheck
前端类型检查
cd apps/frontend && npx svelte-check --threshold error 2>&1 | tail -20
cd apps/frontend && npx svelte-check --threshold error 2>&1 | tail -20
Shared packages
共享库
cd packages/server && npx tsc --noEmit 2>&1 | head -20
Fix any type errors introduced by the migration. Common causes:
- Import path changed but the exported symbol name also differs → check the actual export
- Package hasn't been built yet → `pnpm --filter @portal/server build`
- Circular dependency introduced → check with `pnpm run check:circular`cd packages/server && npx tsc --noEmit 2>&1 | head -20
修复迁移引入的任何类型错误。常见原因:
- 导入路径已更改但导出符号名称也不同 → 检查实际导出
- 包尚未构建 → `pnpm --filter @portal/server build`
- 引入了循环依赖 → 使用`pnpm run check:circular`检查Step 5: Residual Check
步骤5:残留检查
Verify no old import paths remain:
bash
grep -r "<old-import-path>" apps/ packages/ --include="*.ts" --include="*.svelte" -lIf any remain, they may be in:
- Dynamically constructed import strings (require manual inspection)
- Test fixture data (strings, not imports — may be intentional)
- Comments or docs (update if they describe the API)
验证是否存在旧的导入路径:
bash
grep -r "<old-import-path>" apps/ packages/ --include="*.ts" --include="*.svelte" -l如果仍有残留,可能位于:
- 动态构造的导入字符串(需要手动检查)
- 测试 fixture 数据(字符串而非导入 — 可能是有意为之)
- 注释或文档(如果描述API则需更新)
Step 6: Run Tests
步骤6:运行测试
bash
npx vitest run apps/api --reporter=dot
npx vitest run apps/frontend --reporter=dotIf tests fail, determine if it's a mock issue (mock path still points to old module) or a real regression.
bash
npx vitest run apps/api --reporter=dot
npx vitest run apps/frontend --reporter=dot如果测试失败,判断是模拟问题(模拟路径仍指向旧模块)还是真正的回归错误。
Step 7: Atomic Commit
步骤7:原子提交
Stage only the migrated files. Commit with a scope that identifies the migration:
refactor(imports): migrate @portal/shared/server/auth → @portal/server/auth
Affects 23 files across apps/api, apps/frontend, packages/server.
All typechecks pass. Full test suite green.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>仅暂存已迁移的文件。提交时使用标识迁移的作用域:
refactor(imports): migrate @portal/shared/server/auth → @portal/server/auth
Affects 23 files across apps/api, apps/frontend, packages/server.
All typechecks pass. Full test suite green.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>Common Migration Patterns
常见迁移模式
Before running, map out your project's source-to-target pairs. Document these in your project-level CLAUDE.md. Examples:
| Pattern | From (old) | To (new) |
|---|---|---|
| Package rename | | |
| Path restructure | | |
| Index consolidation | | |
| Framework alias | | |
运行前,规划项目的源-目标映射。将这些记录在项目级别的CLAUDE.md中。示例:
| 模式 | 源(旧) | 目标(新) |
|---|---|---|
| 包重命名 | | |
| 路径重构 | | |
| 索引合并 | | |
| 框架别名 | | |
Arguments
参数
- : Migration description
$ARGUMENTS- — import path migration
"@old/pkg/utils → @new/pkg/utils" - — file move
"move packages/server/src/auth.ts to packages/server/src/auth/index.ts" - — package rename
"rename @company/old-shared → @company/core" - If empty, ask for source and target
- : 迁移描述
$ARGUMENTS- — 导入路径迁移
"@old/pkg/utils → @new/pkg/utils" - — 文件移动
"move packages/server/src/auth.ts to packages/server/src/auth/index.ts" - — 包重命名
"rename @company/old-shared → @company/core" - 如果为空,询问源和目标
Anti-Patterns
反模式
- Never use Edit tool file-by-file for bulk migrations — use instead
grep | xargs sed - Never migrate before deduplication check — duplicate migrations cause import conflicts
- Never commit without typecheck — silent import breakage is worse than a failed commit
- Never skip the residual check — 2 files left pointing to the old path can cause subtle runtime errors
- 绝不为批量迁移使用Edit工具逐文件编辑 — 改用
grep | xargs sed - 绝不在去重检查前执行迁移 — 重复迁移会导致导入冲突
- 绝不跳过类型检查就提交 — 静默的导入损坏比提交失败更严重
- 绝不跳过残留检查 — 剩余2个指向旧路径的文件可能导致微妙的运行时错误