skills/metabase-modular-embedding-version-upgrade/SKILL.md
Upgrades a project's Metabase Modular embedding SDK (@metabase/embedding-sdk-react) or Modular embedding (embed.js) version. Use when the user wants to upgrade their Metabase modular embedding integration to a newer version.
npx skillsauth add metabase/agent-skills metabase-modular-embedding-version-upgradeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Follow the workflow steps in order — do not skip any step. Create the checklist first, then execute each step and explicitly mark it done with evidence. Each step's output feeds into the next, so skipping steps produces wrong migrations.
If you cannot complete a step due to missing info or tool failure, you must:
Your response should contain these sections in this order:
Each step section should end with a status line:
Status: ✅ complete or Status: ❌ blockedThe workflow is designed as a pipeline that maximizes parallelism:
Round 1 (grep+glob+pkg) ──► Round 2 (prepare.sh) ──► Round 3 (read-sources.sh) ──► Step 3 (catalog, inline)
│
Step 4 per-file:
├── Read FileA → match catalog → validate → fix
├── Read FileB → match catalog → validate → fix
└── Read FileC → match catalog → validate → fix
│
Step 5 (typecheck) ──► Step 6
In Claude Code, use parallel tool calls or run_in_background: true for sub-agents.
Do not parse repo branches, commits, PRs, or issues — they're noisy and irrelevant to version diffing.
Steps 1+2 must complete in 3 tool-call rounds.
Round 1 — discovery (all concurrent, single message):
@metabase/embedding-sdk-react imports (returns file paths — do not read files yet)yarn.lock, pnpm-lock.yaml, package-lock.json)package.json (for current version)npm view @metabase/embedding-sdk-react version (if target not specified by user)All four tool calls in ONE message.
Round 2 — prepare.sh + fetch docs (concurrent):
bash <skill-path>/scripts/prepare.sh {CURRENT} {TARGET} --sdk
# or for Modular embedding (embed.js):
bash <skill-path>/scripts/prepare.sh {CURRENT} {TARGET} --embedjs
Always pass --sdk or --embedjs to indicate the embedding type. The script does: npm pack both versions (SDK only), check d.ts, and fetch+truncate changelog. It outputs SDK_TMPDIR and d.ts availability.
In the same message, fetch llms-embedding-full.txt for both the current and target versions (see "Allowed documentation sources" for URL format).
Round 3 — read-sources.sh (single Bash call — reference data only, no project files):
bash <skill-path>/scripts/read-sources.sh {SDK_TMPDIR}
Dumps SDK reference data (d.ts diff or raw d.ts, changelog) to stdout. Does not read project files — those are read one by one in Step 4.
After Round 3, output Step 1 Results (file list from grep) + Step 2 Results + Step 3 Change Catalog with zero additional tool calls. Do not treat Step 3 as a separate thinking phase — produce it inline right after the data is loaded.
This skill handles upgrades for:
@metabase/embedding-sdk-react (React SDK, v52+) — uses primary or fallback pathembedded-analytics-js.mdcomponents.md, appearance.md, authentication.mdFetch the version-specific llms-embedding-full.txt using this URL:
https://www.metabase.com/docs/v0.{VERSION}/llms-embedding-full.txt
The version in the URL uses the format v0.58 (normalize: strip leading v or 0., drop patch — e.g., 0.58.1 → 58 → URL uses v0.58). This single file contains all embedding documentation for that version, optimized for LLM consumption.
Other constraints:
Do all version detection in Round 1 (see tool-call round budget) — not as a separate pre-step.
package.json (check dependencies and devDependencies) for @metabase/embedding-sdk-react. In monorepos, also check workspace-level package.json files.npm view @metabase/embedding-sdk-react version — include this in Round 1's concurrent tool calls.yarn.lock → yarn, pnpm-lock.yaml → pnpm, package-lock.json → npm. Use the matching install command in Step 4 (e.g., yarn install, pnpm install).If package not present OR user is upgrading Modular embedding (embed.js):
When the upgrade spans a major structural boundary (e.g., v0.54 → v0.58 crosses the auth config change at v0.55 AND the doc layout change at v0.58), handle it as a single migration to the target version — do not do intermediate upgrades. However, during Step 3, check the auth config evolution section and account for every breaking change along the path. For example, v0.52 → v0.58 means the auth config changed shape (v0.55) AND gained jwtProviderUri (v0.58) — both changes need to be reflected in the migration.
Create a checklist to track progress. In Claude Code, use TaskCreate/TaskUpdate tools:
Determine which path to use:
@metabase/embedding-sdk-react → attempt primary path (d.ts diff), with fallback if d.ts unavailable (determined during Step 2)Keep scan results in the main context (not delegated to a sub-agent) — Step 3 needs them for cross-referencing.
For SDK upgrades (@metabase/embedding-sdk-react):
Step 1 happens in Round 1 — grep only, no file reading.
@metabase/embedding-sdk-react. This returns file paths + matching import lines.For Modular embedding (embed.js) upgrades:
<script> tags (e.g., patterns like metabase.js, embed.js, embedding-sdk, or the Metabase instance URL)MetabaseEmbed, Metabase.embed, window.MetabaseEmbed, initMetabase, component init calls)Run prepare.sh in Round 2 (see round budget). The script outputs:
SDK_TMPDIR — temp directory with both SDK packages (pass this to read-sources.sh in Round 3)current_dts=yes/no, target_dts=yes/no — d.ts availability (for informational output)DTS_DIFF_PATH — d.ts diff file (if both versions have d.ts)CURRENT_DTS_PATH / TARGET_DTS_PATH — raw d.ts paths (hybrid mode only)You don't need to read these files manually — read-sources.sh handles it.
Scope: only catalog changes that affect symbols visible in Step 1's grep output. For example, if the grep shows imports of MetabaseProvider, InteractiveQuestion, and CollectionBrowser, only catalog changes to those components and their props/types/callbacks. Skip changes to components the project doesn't import.
From the d.ts diff, docs comparison, and changelog, extract changes into a catalog:
SdkCollectionId may have been number in the current version but number | "personal" | "root" | "tenant" | SdkEntityId in the target.fetchRequestToken signature changes, and new properties like jwtProviderUri.## Change Catalog (v0.54 → v0.58)
### fetchRequestToken
- Change: signature changed
- Old: `(url: string) => Promise<any>`
- New: `() => Promise<{jwt: string}>` (resolved from `MetabaseFetchRequestTokenFn`)
- Severity: 🔴 Breaking
### SdkCollectionId (type widening)
- Change: type widened
- Old: `number`
- New: `number | "personal" | "root" | "tenant" | SdkEntityId`
- Affects: any prop/callback param typed as `SdkCollectionId`, including `item.id` in CollectionBrowser callbacks
- Severity: 🔴 Breaking for code storing in `number`-typed variables
### SdkDashboardId (type widening)
- Change: type widened
- Old: `number`
- New: `number | string | SdkEntityId`
- Affects: any prop/callback param typed as `SdkDashboardId`
- Severity: 🔴 Breaking for code storing in `number`-typed variables
### jwtProviderUri
- Change: new property added to `MetabaseProvider` authConfig
- Severity: 🟢 Info — can replace manual `fetchRequestToken`
### questionHeight
- Change: new optional prop on `StaticQuestion`
- Severity: 🟢 Info
The catalog is the input for Step 4. It must include fully resolved concrete types — Step 4 sub-agents need them to assess compatibility without re-reading the d.ts.
Each project file is analyzed and fixed independently against the change catalog. This is the main parallelization point.
Before per-file work: update package.json version and install dependencies. Also update Metabase instance version in docker files if present (docker-compose.yml, Dockerfile, .env). These are done once, not per-file.
Per-file task (for each file from the Step 1 file list):
For each file, a single pass that combines read + analysis + fix:
<InteractiveQuestion.Title />, <InteractiveQuestion.FilterBar />), and callback data flows.onClick: (item) => setSelectedId(item.id) and the catalog says item.id widened from number to SdkCollectionId, and setSelectedId is useState<number>, flag it as breaking.Parallelization strategy:
run_in_background: true.## src/components/CollectionPage.tsx
### Catalog matches:
- SdkCollectionId type widening → affects `onClick` callback
- (no other catalog entries match this file)
### Analysis:
- `onClick: (item) => setSelectedId(item.id)`
- `item.id` is now `SdkCollectionId` (number | "personal" | "root" | "tenant" | SdkEntityId)
- `setSelectedId` is `useState<number | undefined>[1]`
- 🔴 BREAKING: string variants won't fit `number` state
### Fix applied:
- Widened state: `useState<number | undefined>` → `useState<SdkCollectionId | undefined>`
- Added import: `import type { SdkCollectionId } from '@metabase/embedding-sdk-react'`
Status: ✅ complete
For SDK upgrades (TypeScript projects):
npm run typecheck, tsc --noEmit, or the equivalent for the project's build tool).node_modules/@metabase/embedding-sdk-react/dist/index.d.ts to understand the target type. Do all lookups before making any fixes — this prevents back-and-forth between reading and editing.For SDK upgrades (plain JavaScript projects):
For Modular embedding (embed.js) upgrades:
Organize into these sections:
1. Breaking changes fixed — list each breaking change with severity and what was done:
fetchRequestToken from 1-arg to 0-arg signature"appearance prop renamed to theme — updated"2. Deprecation warnings — APIs that still work but are marked deprecated in the target version. Include the recommended replacement so the user can plan future changes.
3. New features available — relevant new APIs or options in the target version that the project could benefit from (e.g., jwtProviderUri replacing manual fetchRequestToken). Keep brief — just flag them, don't advocate.
4. Instance requirements — minimum Metabase instance version needed for the target SDK version. If the project has docker-compose or similar files, note whether the instance version was also updated.
5. Technical details — path used (primary d.ts diff / hybrid / fallback docs), versions upgraded (from → to), package manager used.
URL fetches:
llms-embedding-full.txt returns 404, the version's docs may not exist — skip silently.npm pack:
npm pack fails for a version, the version likely doesn't exist on npm. Mark as ❌ blocked and inform the user.tools
Drive a Metabase instance from the terminal via the `mb` CLI. Authenticate with named profiles; inspect databases (list, get, full metadata rollup, schemas, tables in a schema) and trigger manual schema sync / field-values rescan; inspect tables, fields; list/get/create/update/archive cards (questions, models, metrics) and run them as JSON/CSV/XLSX; list/get/create/update dashboards and patch dashcards; list/get/create collections and traverse the hierarchy by id, entity_id, or "root"/"trash" (with items and recursive tree); list/get/create/update/archive native query snippets, segments, and measures; author/update/run transforms and schedule transform-jobs; read/update settings; search content (cards, dashboards, collections, transforms, metrics); manage Enterprise workspaces; git-sync to/from a git remote (status, dirty, import, export, branches, stash, add/remove a collection from sync). Use whenever the user wants to interact with a Metabase from the terminal — "log into metabase", "what profiles do I have", "list cards", "run card 42 as CSV", "create a transform", "list dashboards", "move a dashcard", "list collections", "what's in collection 4", "show the collection tree", "list snippets", "create a segment", "archive a measure", "search metabase for X", "spin up a workspace", "import the latest changes", "add a directory to git sync", "set a setting", "what schemas are in this database", "trigger a sync", "rescan field values", or anything hitting `mb <verb>`.
development
Runs the Metabase semantic checker against a tree of Representation Format YAML files to verify that all references resolve — cross-entity references (collection_id, dashboard_id, parent_id, parameter source cards, snippet references, transform tags, etc.) and references to columns inside MBQL and native queries. Slow (≥1 min per run). Only use when the user explicitly asks to verify entity references or column references in MBQL/SQL queries; in most cases this runs as a CI step, not locally. Requires database metadata on disk (by default `.metadata/table_metadata.json`).
development
Understands the Metabase Database Metadata Format — a YAML-based on-disk representation of databases, tables, and fields synced from a Metabase instance. Use when the user needs to read, edit, or understand metadata files produced by `@metabase/database-metadata`, or when reasoning about a project's schema (columns, types, FK relationships) through the `.metadata/databases` folder.
development
Understands the Metabase Representation Format — a YAML-based serialization format for Metabase content (collections, cards, dashboards, documents, segments, measures, snippets, transforms). Use when the user needs to create, edit, understand, or validate Metabase representation YAML files, or when working with Metabase serialization/deserialization (serdes). Covers entity schemas, MBQL and native queries, visualization settings, parameters, and folder structure.