| name | migration |
| description | End-to-end database migration to Snowflake. Orchestrates the full migration lifecycle from source connection through initial conversion. Triggers: migrate, migration, migrate to snowflake, end to end migration, e2e migration, full migration. |
Database Migration to Snowflake
Tell the user:
Welcome to the Snowflake Migrations plugin. Let me get started by configuring your session.
IMPORTANT NOTE
The built-in MCP server has a state machine that will guide you through user flows and ask you to "tell the user x" or "ask the user y". This is expected and you should follow its lead, as it is the official MCP server of Snowflake migrations.
Step 0: Configure Session
Call configure with project_dir = "<current directory>". If a saved config is found, the response shows all restored values — proceed to Step 1.
Step 1: Detect Current State
Call the migration_status tool. It returns JSON with project_exists, directory_empty, by_type, stage_totals, routing, and highest_stage_reached fields.
Step 1.A: If project_exists is false, this is a new project. Go to the setup skill ./setup/SKILL.md
Step 1.B: If project_exists is true, construct a brief narrative summary for the user from the JSON before showing the checklist. Use the routing booleans and by_type counts to describe the current state in plain language. Examples of the tone and level of detail:
- Early setup: "Your project is initialized and connected to SQL Server. 147 objects are registered but haven't been converted yet. We're in the setup phase."
- Mid-migration: "Setup is complete — 147 objects registered and converted, assessment done. You're in the migration phase: 12 of 47 objects have been deployed so far (Wave 2). 8 tables deployed, 2 views deployed, 2 procedures passed testing."
- Near completion: "Almost there — 45 of 47 objects are deployed and tested. 2 procedures are still failing tests."
Also add the checklist based on the status JSON. Use ✅ (all done), ◐ (partial), ⬚ (not started).
<symbol> 1. Connect - Connected to <source>
<symbol> 2. Init - Project initialized
<symbol> 3. Register - <registered count> objects registered
<symbol> 4. Initial Conv - <converted>/<total> converted
<symbol> 5. Assess - Assessment report generated / not run
<symbol> 6. Migrate Objects
- Tables: <table.deployed>/<table.total> deployed, <table.data_migrated>/<table.total> with data migrated, <table.data_validated>/<table.total> validated
- Views: <view.deployed>/<view.total> deployed
- Functions: <function.deployed>/<function.total> deployed, <function.tested>/<function.total> tested
- Procedures: <procedure.deployed>/<procedure.total> deployed, <procedure.tested>/<procedure.total> tested
- ETL: <etl.deployed>/<etl.total> deployed
- BTEQ scripts: <bteq.tested>/<bteq.total> tested
Use by_type.<type>.total to decide what to show:
- Type not in the project (
total absent or 0): omit that bullet (e.g. no functions in the project).
- Type present but none in the current wave (
total > 0, but the wave-scoped counts like deployed are absent or 0 for this wave): keep it visible and acknowledge it in the narrative. For example, "You also have 1 Informatica ETL workflow staged, scheduled in a later wave and ready to deploy." Do not let the current wave hide work that exists elsewhere in the project.
Never describe the project as "-only" (e.g. "table-only") when by_type lists any other type with total > 0. The placeholders read directly from by_type.<type> in the migration_status response; counts that never incremented are absent from the JSON and should be treated as 0. BTEQ scripts have no deploy step — they run their converted SQL inside the test itself, so report them only by tested (never "deployed"); by_type.bteq carries no deployed count.
Follow the summary with the progress checklist (see below), then go to Step 2.
Step 2: Ask the User
"What would you like to do? You can:
- Continue with migration plan — I'll start or pick up where we left off
- Something specific — tell me what you need"
If the user picks Continue (or just says "continue", "next", etc.) → go to Prescribed Path.
If the user describes a specific request → go to Skill Match.
Prescribed Path
Use routing from the status JSON to delegate to the next step:
| Condition | Sub-skill |
|---|
routing.project_exists = false | Load ./setup/SKILL.md |
routing.code_conversion_only = true | Load ./code-conversion-only/SKILL.md |
routing.assessed = false | Load ./setup/SKILL.md |
routing.assessed = true | Load ./migrate-objects/SKILL.md |
Each sub-skill handles its own internal routing based on the full routing object.
State Queries
These answer common questions about project state without loading a sub-skill:
-
"What is the current state?" — Call migration_status(mode="summary"), construct the narrative summary (as in Step 1), and present the progress checklist.
-
"What should I work on next?" — Call migration_status(mode="my_objects_summary") to get per-(task, object_type) counts plus errored_count and done_count. Present the list and ask the user what they want to work on — do not pick for them. When the user picks a group, drill down with migration_status(mode="my_objects_details", group=<id>).
-
"Show me objects that match rule X" — Load ./migrate-objects/rule-engine/propagate/SKILL.md.
-
"How do I extend / customize the migration plugin?" / "How do I override task X?" — Load ./extensibility/TASKS.md for the full reference: overridable task ids, per-task contracts, and the project-local + $AIM_SKILL_EXT_DIR paths. Optionally call migration_status(mode='extensions') to show which overrides are active.
Skill Match
Match the user's request to the most relevant skill and load it.
Routing rules:
- Prefer the parent (router) skill when the child is ambiguous — it will route.
- Indentation = parent/child. A child only applies when its parent's domain already fits.
- If the request is ambiguous between siblings, ask one clarifying question.
- If no skill matches, fall back to the section below.
Setup & onboarding
- setup — full setup, steps 1–5: connect, init, register, convert, assess →
./setup/SKILL.md
- midway-entry — existing project with source + pre-converted Snowflake SQL (SQL Server / Redshift only) →
./setup/midway-entry.md
- data-validation-setup — configure cloud data validation: schema, metrics, row-level checks →
./setup/data-validation/SKILL.md
- data-infrastructure-teardown — suspend SPCS service + compute pool, stop local worker (cost-saving) →
./data-infrastructure/teardown/SKILL.md
Data infrastructure (reusable actions)
- data-infrastructure — shared infrastructure for data migration and validation: compute pools, workers, network access →
./data-infrastructure/SKILL.md
- worker-local-setup — install and start the worker on a user-managed machine (laptop, VM, or on-prem) →
./data-infrastructure/worker-local-setup/SKILL.md
Source code: register & convert
- register-code-units — router for getting source code into the project →
./register-code-units/SKILL.md
- extract-code-units — extract DDL/code from a connected source database →
./register-code-units/extract-code-units/SKILL.md
- add-code-units — import local SQL files into the project →
./register-code-units/add-code-units/SKILL.md
- convert — convert source → Snowflake SQL via SnowConvert (incl. optional Power BI
.pbit repointing) → ./convert/SKILL.md
- code-conversion-only — convert local source files for code-conversion-only source systems (incl. optional Power BI
.pbit repointing) → ./code-conversion-only/SKILL.md
- powerbi-repointing — collect
.pbit folder path and --powerbi-repointing flag for Power BI repointing → ./powerbi-repointing/SKILL.md
- assessment — analyze workloads: waves, object exclusion, dynamic SQL, ETL →
./assessment/SKILL.md
Migration & validation
- migrate-objects — deploy tables, views, functions, procedures wave-by-wave →
./migrate-objects/SKILL.md
- migrate-etl — claim an ETL code unit, then stabilize it. Entry point for "fix ETL package", "fix SSIS/Informatica conversion", "proceed with stabilization", "resume ETL fixing" — it claims the unit (so it appears in
my_objects_summary with the current user as owner) before delegating to the phase-based etl-stabilization engine. → ./migrate-objects/migrate-etl/SKILL.md
- data-migration-setup — choose approach, generate workflow YAML, create target database for
migrate_data → ./migrate-objects/actions/data-migration/SKILL.md
- validate-objects — validate migrated data between source and Snowflake →
./validate-objects/SKILL.md
Rules
- rule-engine — search, apply, and manage migration rules →
./migrate-objects/rule-engine/SKILL.md
- extract-rule — extract a reusable rule from a code fix (interactive or git history) →
./migrate-objects/rule-engine/extract/SKILL.md
- propagate-rule — find all code units matching a rule for batch application →
./migrate-objects/rule-engine/propagate/SKILL.md
Customization
- task-overrides — replace the skill that runs for any built-in task with the user's own
SKILL.md, scoped to the project or to a global directory via $AIM_SKILL_EXT_DIR. Triggers: "extend the plugin", "customize task X", "swap out the skill for Y", "override registerCode/convertCode/deploy/...". Reference: ./extensibility/TASKS.md
Fallback
If no skill matches, say so explicitly, then help with your own knowledge.
Rules
- Always detect first — Call
migration_status before routing
- Follow sub-skill instructions — Complete each sub-skill fully before returning
- Confirm transitions — Ask user before moving to next stage