← All guides13 min read

AI Shopify migration with a coding agent: the Graftport playbook

How to run an AI Shopify migration end to end with Claude Code, Cursor, Windsurf, or Copilot driving the Graftport CLI, with the costly steps gated by a human.

A Shopify replatform is mostly iteration. You pull a sample of products, notice a custom attribute that does not fit a Shopify product field, edit a mapping expression, validate it against more rows, find a new edge case, edit again. Repeat for products, customers, orders, redirects, pages. This is the kind of work an AI coding agent is unusually good at — short loops, structured feedback, and a clear definition of "this passes." This guide is the playbook for handing that loop to your agent and keeping the costly steps on a human.

If you have not yet created the migration itself in the Graftport app, read Setting up your first Graftport migration first. The CLI takes over after the wizard, not instead of it.

1. What "AI Shopify migration" actually means here

The phrase gets used loosely. In Graftport, it means something narrow and concrete: an AI coding agent — Claude Code, Cursor, Windsurf, Copilot, or anything else with a shell tool — drives the Graftport CLI through the iterative phase of a migration. The agent investigates source data, drafts JSONata mapping expressions, validates them against real rows, publishes new mapping versions, and runs dry-runs to inspect the projected output. You stay in the loop for the steps that cost real money or are destructive: real loads, run cancels, record retries.

What the agent is not doing:

  • Spinning up the migration itself. You create the project, connect the source store and destination Shopify, and pick the resource templates in the app wizard.
  • Writing to your source store. Source credentials are read-only and Graftport never writes back to Magento, WooCommerce, or a source Shopify, regardless of who is driving.
  • Spending platform credits or Shopify API quota without you. Every cost-incurring command blocks for a human yes and prints a live cost estimate to stderr first.

What the agent is doing is the labour-intensive middle: turning "there is a weight_in_kg attribute on Magento products and Shopify wants grams" into a JSONata expression that handles the unit conversion, the missing values, and the outliers — and proving the expression works against 50 sampled rows before it ships.

2. Why migrations are a good fit for coding agents

Plenty of "AI for X" claims age badly. Migration mapping ages well for a specific reason: every iteration has a sharp, structured signal.

  • Tight feedback loop. A mappings validate call against a sample of rows returns in seconds. The agent edits a JSONata file, re-runs validation, and gets a deterministic pass/fail per row.
  • Structured error codes. Validation does not return "something looks wrong." It returns codes the bundled skill maps to specific JSONata patterns. The agent already knows that an amount mismatch is almost always a unit conversion problem, and that a missing- required failure points at a field the source does not always carry.
  • Versioned mappings. Every mappings publish is a new immutable version. The agent can ship freely because rolling back to a prior version is one command away.
  • Read-only by default. Most of the CLI is read-only. The two state-changing commands the agent is allowed to call are the cheapest ones: publish a mapping version (metadata only) and start a dry-run (zero Shopify writes).

The combination matters. The work is boring, repetitive, and benefits from someone who never gets tired. The signal is sharp enough that the agent does not drift. And the rail keeps it from doing anything expensive without you.

3. The four-step loop

Every iteration the agent runs follows the same shape. The bundled skill spells it out so the agent does not improvise.

Step 1 — Investigate

The agent pulls real source rows for the resource it is working on. No schema diagram, no second-hand description — the raw JSON the source store actually returns:

graftport source rows <migration_id> product --limit 5

This is the part you cannot skip. Every source store has a long tail of custom attributes, half-filled fields, and historical oddities. The agent sees them on the first call.

Step 2 — Draft

The agent reads the current mapping for that resource and forks it to a local file it can edit:

graftport mappings show <mapping_id> --raw > current.jsonata

Then it edits current.jsonata to handle whatever the samples revealed — a unit conversion, a status enum mismatch, a tag list that needs splitting on commas.

Step 3 — Validate

Before publishing anything, the agent validates the new expression against a fresh sample of source rows:

graftport mappings validate <mapping_id> --jsonata current.jsonata --limit 50 --pretty

The validator returns structured error codes per failing row. The skill teaches the agent which JSONata pattern fixes each one. Iterate until the sample passes.

Step 4 — Publish, then dry-run

When the sample is clean, the agent publishes the new mapping version and starts a dry-run to see the end-to-end projected output:

graftport mappings publish <mapping_id> --jsonata current.jsonata --notes "fix AMOUNT_MISMATCH"
graftport runs start <migration_id> --dry-run

Both of these are agent-allowed. The publish is a metadata write; the dry-run computes payloads without pushing to Shopify. Zero load cost in either direction.

For the deeper mechanical detail — what JSONata patterns the skill suggests for each error code, how to compose the validate / publish cycle for a multi-resource migration — see Automating JSONata mappings with AI.

4. A brief tour of the CLI

You do not need to know every command to drive the loop above, but it helps to know how the surface area is shaped. The CLI groups its commands by domain:

GroupCommands
authlogin / status / logout
migrationslist / show / resources
mappingslist / show / validate / publish
runslist / show / status / estimate / start / cancel
recordsfailures / errors / show / loaded / retry
sourcerows / raw
skill(bare) / install

Every command emits JSON on stdout by default; pass --pretty for human-readable output. Exit codes are stable: 0 ok, 1 error, 2 usage, 3 a human-gated action was declined. The 3 code is what lets your wrapping scripts (and the agent) tell "you said no" apart from "something broke."

The skill group is the install step: graftport skill install auto-detects the coding agents present on your machine and writes the skill document to the right place for each. There is no separate API to configure. For the install details and per-agent paths, see Using the Graftport CLI with Claude Code.

5. What the agent does, what stays on you

It is easier to trust an agent when the boundary is explicit. The Graftport CLI splits state-changing actions into two tiers, and the bundled skill makes the boundary the agent's first rule.

The agent does, without asking:

  • All read-only commands — listing migrations, inspecting mappings, showing failed records, pulling source rows.
  • mappings publish — a metadata write. It flags downstream records for re-load on the next run, which is itself gated.
  • runs start --dry-run — computes the full payload Shopify would receive, but stops short of pushing it. Zero load cost.

You do, after the agent presents the command:

  • runs start without --dry-run — the real load. Costs Shopify API calls and platform credits per record.
  • runs cancel — destructive; may lose in-flight work on records already partway through.
  • records retry — re-loads one record; small but real cost.

The gated commands print the resolved action to stderr, including a live cost estimate for runs start, then block on a yes. The bundled skill explicitly forbids the agent from ever passing --yes to bypass the gate. The agent's job is to compose the right command, explain why, and stop. Your job is to press enter.

The trust angle is covered in depth in Human approval gates for AI Shopify migrations — including why this matters more for migrations than for general coding work.

6. Which agents work

The CLI does not care which agent you use. Anything with a shell tool can call it. The skill — the Markdown document that teaches the agent how to use the CLI — has different on-disk conventions per product, so the install command handles those for you.

AgentInstall
Claude CodeAuto-detected; lands at ~/.claude/skills/graftport-migration-engineer/
Claude DesktopAuto-detected; shares the path with Claude Code
WindsurfAuto-detected; merged into ~/.codeium/windsurf/memories/global_rules.md
CursorManual paste into Settings → Rules → User Rules
GitHub CopilotManual drop into .github/copilot-instructions.md
Aider / AGENTS.md / customManual paste into your agent's instructions file

For the agents that need a manual paste, run graftport skill > skill.md and place the file where your agent expects it. Cursor only reads User Rules from its Settings UI; Copilot reads per-repo instructions; AGENTS.md is project-scoped by definition. None of these are second-class — they read the same skill text — they just need one extra step.

7. A realistic first session

Concrete example. You have a Magento migration created in the app, the source connected, the destination Shopify connected, and the default resource templates seeded. You open Claude Code in any working directory (it does not need to be a repo — the CLI's state lives in ~/.graftport/config.json, not in the project).

You ask the agent: "Take a look at the product mapping for migration mig_8f2a and clean up any field issues you find against a sample of 50 rows."

The agent runs graftport mappings list mig_8f2a to find the product mapping ID, graftport source rows mig_8f2a product --limit 5 to see real samples, graftport mappings show <map_id> --raw > current.jsonata to fork the current expression, and graftport mappings validate <map_id> --jsonata current.jsonata --limit 50 to see what fails. It edits the file, re-validates, and once the sample passes, it runs graftport mappings publish ... --notes "fix weight unit + status enum".

Then it tells you what it changed and proposes graftport runs start mig_8f2a --dry-run to verify end-to-end. You hit yes (or just let it run — dry-run is agent-allowed and costs nothing). You inspect the result in the Data tab in the app. Cycle complete.

For the worked example of setting up exactly this in Claude Code, including the headless / CI install path, read Using the Graftport CLI with Claude Code.

8. What does not change

Two things stay the same as a hand-run Graftport migration.

The first is the wizard. You still create the migration at app.graftport.com/migrations/new, connect credentials, pick which resource types to seed. The CLI does not replace that step and does not try to.

The second is the run model. Every load is still idempotent — records are tracked by their source identity, so anything already loaded is skipped. Re-running a migration on go-live night picks up only the delta, agent-driven or not. The dry-run safety net works the same way. For the launch-night playbook, see Re-running a migration on go-live — none of it changes when an agent is the one composing the commands.

What the agent adds is leverage on the part of the project that used to eat a week per source: the mapping phase.

Related reading

Ready to point your agent at a real migration? Sign up at app.graftport.com and create the project, then jump to /ai-migrations for the install commands and the agent-by-agent setup.

Ready to migrate?

Connect a source store, dry-run a migration, see the exact Shopify result before a single record lands. The same platform your team will use on go-live night.

Get started See the calculator
Related guides
Using the Graftport CLI with Claude Code: install to first publish
Set up the Graftport CLI and migration-engineer skill in Claude Code, then drive a real Shopify migration through the validate and publish l
Human approval gates for AI Shopify migrations: the Graftport contract
Why an AI coding agent should never push to Shopify on its own, and how Graftport's two-tier CLI contract enforces a human gate on every cos
Automating JSONata Shopify mapping with an AI coding agent
How the Graftport CLI lets an AI agent investigate source rows, fix JSONata mapping errors against structured validation codes, and publish