AI-assisted mapping
Iterating a JSONata mapping until every record transforms cleanly is the most time-consuming part of a migration. With the graftport CLI plus the bundled agent skill, you can hand that loop to your favourite coding agent — Claude Code, Cursor, Windsurf, Copilot Workspace, anything with a shell tool — and have it sample real source rows, edit the JSONata, re-validate, and publish a new version when every sample passes.
You stay in control of the migration: the agent never triggers an extract or a load. It only iterates the mapping.
Setup
Install the CLI:
uv tool install graftport # recommended
# or
pip install graftportSign in once. The CLI stores its config in ~/.graftport/config.json.
graftport auth loginYou’ll be asked for your Graftport project URL, the anon key, and an
access token. The access token is the JWT from your browser session —
in DevTools, Application → Cookies → sb-…-auth-token. Tokens are
short-lived; when commands start returning 401, run
graftport auth login again.
Hand the skill to your agent
Every install of graftport ships with a Markdown skill document
that teaches an agent how to drive the CLI. The CLI can install it
directly into your coding agent’s user-global folder — you only need
to do this once per machine, not per project:
graftport skill install --prettyThis auto-detects which coding agents are installed for your user and writes the right file for each:
| Agent | Where the skill lands |
|---|---|
| Claude Code and Claude Desktop | ~/.claude/skills/iterating-graftport-mappings/ (one install serves both apps) |
| Windsurf | ~/.codeium/windsurf/memories/global_rules.md (idempotent block) |
Re-running is safe — the marker-bracketed block in Windsurf’s global
rules file is replaced in place. Pass --for <agent> to target a
specific tool or --for all to write every supported one.
Other agents. Cursor’s User Rules live only in its Settings UI,
Copilot Workspace reads .github/copilot-instructions.md per-repo,
and AGENTS.md is project-scoped by definition — none of these have
a user-global on-disk location, so the CLI doesn’t try to install
into them. For those, run
graftport skill > graftport-skill.mdand place or paste the file where the tool expects it.
What the agent can do
- Discover the mappings for a migration:
graftport mappings list <migration_id>. - Read the current JSONata into a local file:
graftport mappings show <mapping_id> --raw > current.jsonata. - Sample real source rows — the same shape the transform worker
feeds into JSONata:
graftport source rows <migration_id> <resource_type>. - Validate a draft against those rows, with grouped error output:
graftport mappings validate <mapping_id> --jsonata current.jsonata. - Publish a new mapping version once every sampled row passes:
graftport mappings publish <mapping_id> --jsonata current.jsonata.
If the mapping is still pinned to a global template, publish forks
it for you automatically — no separate step.
What the agent can’t do
- Trigger an extract run. You do that from the migration page.
- Trigger a load run. You do that from the migration page.
- Touch any other migration than the one you give it.
- Read or modify another tenant’s data. The CLI scopes everything to your account’s JWT.
A typical session
You’ve extracted a Magento store. The product mapping is the global
template, but 12 of 50 sampled records fail with REQUIRED_MISSING
on input_variants[].price. You give your agent the migration ID and
say “iterate the product mapping until every sample passes”. The
agent then:
- Lists the mappings, finds the product one.
- Reads the current JSONata.
- Samples a few failing rows with
--filter-field type_id=simple. - Spots that
pricelives underextension_attributes.tier_prices[0].valuefor those records. - Edits the JSONata to fall back to that path.
- Re-validates against 50 rows: 50/50 pass.
- Publishes the new version with notes describing the change.
You hop into the mapping editor in the UI, see the new version pinned, and start a transform run. Done.
When AI-assisted mapping isn’t the right tool
- One-off tweaks where you already know the change. Editing in the UI is faster.
- Heavily product-specific business logic that only a human knows. The agent can’t read the merchant’s mind — give it the mapping template and your written intent, not a vague “make it work.”
- Loading the data into Shopify. The agent stays out of that loop on purpose: cut-overs need a human in the chair.