Skip to content
Development
Skill

/metabase-data-app-migrate

Migrate an existing Metabase data app that Metabase marks Outdated (its `data_app.yaml` `version` is below the data-app contract version the installed skills and SDK target) to the current version, one upgrade at a time, with a resumable procedure. Use when Metabase shows an app

BOOST
From plugin
metabase
50k32 skills11 agents23 commands
Install
$ npx -y skills add metabase/metabase --skill metabase-data-app-migrate --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/metabase-data-app-migrate

Context preview

The summary Claude sees to decide when to auto-load this skill.

Migrate an existing Metabase data app that Metabase marks Outdated (its `data_app.yaml` `version` is below the data-app contract version the installed skills and SDK target) to the current version, one upgrade at a time, with a resumable procedure. Use when Metabase shows an app

SKILL.md

metabase-data-app-migrate.SKILL.md
name: metabase-data-app-migrate
description: Migrate an existing Metabase data app that Metabase marks Outdated (its `data_app.yaml` `version` is below the data-app contract version the installed skills and SDK target) to the current version, one upgrade at a time, with a resumable procedure. Use when Metabase shows an app as Outdated, `npm run typecheck` or `npm run build` fails after an SDK upgrade, or an existing app's `version` is behind the one the installed skills target. Not for creating an app.

Migrate a data app to the current contract version

A data app declares the contract version its code targets in `data_app.yaml` (`version: N`; a manifest without the field is version 1). Metabase bumps the version it serves only on a breaking change to that contract: the `@metabase/embedding-sdk-react/data-app` API, the bundle factory, the manifest, the `queries/` and `actions/` conventions, or what an app may declare. An app on an older version is marked _Outdated_ in the admin list, hidden from every other user, and refuses to open until it is migrated.

Migration is a walk over **upgrades**: `N -> N+1 -> ... -> M`, one upgrade at a time, each described by a guide in `references/upgrades/`. Nothing is skipped and nothing is remembered between sessions: the app's own files and git history carry all the state.

Four invariants

Every step below follows from these. Never break them.

1. **`version` is written last.** An upgrade's `version: N+1` goes into `data_app.yaml` only after every check of that upgrade passes. 2. **One commit per upgrade, locally.** Push only after the final gates at the target version pass. The version line never moves by more than one per commit. 3. **Compiler and build gates run only at the target version.** The installed SDK is the target, so an app halfway through several upgrades cannot type-check or build. Do not run them earlier and do not "fix" their failures earlier. 4. **Nothing generated is edited by hand.** `savedQuestionSourceId`, `copiedActionId`, `resources_metadata.json`, and `dist/` are written by `npm run build` (`sync-resources`), never by you.

Step 0 - Locate the app and read its state

Work from the app directory, `<repo>/data_apps/<slug>/`. Resolve the repo root with `ROOT="$(git rev-parse --show-toplevel)"`. The final build needs the repo-root `.env.local` credentials (`DATA_APP_MB_URL`, `DATA_APP_MB_API_KEY`). Check them by sourcing the file in a subshell and printing only whether both are set; never print the file or its variables. The key must belong to an admin: the API returns `version` and `outdated` only to admins and refuses an outdated app's metadata to everyone else, so a non-admin key cannot prove anything here.

`npm` below stands for the app's own package manager, the one whose lockfile is committed (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock`). Never introduce a second lockfile.

Read three numbers:

# version committed at HEAD (absent line means 1)
git show HEAD:data_apps/<slug>/data_app.yaml | grep -E '^version:' || echo "version: 1"
# version in the working tree
grep -E '^version:' data_app.yaml || echo "version: 1"
# target: the highest upgrade guide shipped with this skill (no guides means 1)
ls <skill-dir>/references/upgrades/ | sed -nE 's/^v[0-9]+-to-v([0-9]+)\.md$/\1/p' | sort -n | tail -1 | grep . || echo 1

`<skill-dir>` is the directory this SKILL.md was loaded from. The target must equal the `version:` in the data-app scaffolding template installed alongside this skill (`<skills-dir>/*/template/data_app.yaml`), when one is present; if they differ, the skills come from different Metabase releases. **Stop** and tell the user to reinstall all data-app skills with the command shown under Admin > Data apps. Wait for the answer.

Then decide:

| HEAD version | working tree | do | | ------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | equals target | clean | Nothing to migrate. Say so; run the final gates only if the user asked to verify. | | above target | any | **Stop.** There is no downgrade. Either Metabase, the SDK, and the skills are older than the app, or a bump was committed against the wrong instance (`git log -- data_apps/<slug>/data_app.yaml` shows it). Wait for the answer. | | below target | clean | Start at _Step 1_. | | any | dirty under `data_apps/<slug>` | A previous session was interrupted. Go to _Resuming_ first. |

Step 1 - Preflight, once

1. Install the SDK that matches the target Metabase release with the app's package manager (`npm install @metabase/embedding-sdk-react@<tag>` or its equivalent); each upgrade guide names the dist-tag it was written against. The lockfile change is committed with the final upgrade. 2. Confirm the app is template-shaped at its current version: `vite.config.ts` is the one-liner `export default dataAppConfig()` and `src/index.tsx` default

Read more
Ships withmetabase

Metabase is the easy, open-source way for everyone in your company to ask questions and learn from data.

Get the whole plugin

Other skills on metabase.