feat(DATA-2104) Add metabase-to-hex migration skill#705
Conversation
Adds a skill for migrating a Metabase dashboard or single card/question to a Hex app at Clipboard Health: extract the source structure via the Metabase MCP, rewrite SQL onto core dbt models, scaffold the Hex project with the CLI, and finish Input cells / markdown / appLayout via a YAML round-trip. Includes reference docs (CBH stack, gotchas, YAML schemas) and helper scripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (5)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThis pull request adds a complete Metabase-to-Hex migration skill package: a seven-phase playbook, three reference guides, utility scripts for inventory/layout/cell management and Jinja-variable auditing, and a cspell word-list update. ChangesMetabase-to-Hex Migration Skill Package
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit b3f82d7
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
plugins/core/skills/metabase-to-hex/references/gotchas.md (1)
1-6: 💤 Low valueGotcha numbering skips
#8.The document numbers gotchas 1-7, then jumps to 9. Either gotcha
#8was removed during editing, or the numbering should be adjusted. This could cause confusion when cross-referencing between SKILL.md and this file.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@plugins/core/skills/metabase-to-hex/references/gotchas.md` around lines 1 - 6, The gotchas list in "Hex / Metabase migration gotchas — extended catalog" skips number 8 (entries go 1–7 then 9); either restore the missing `#8` entry or renumber the subsequent entries so numbering is sequential and update any cross-references in SKILL.md accordingly; locate the numbered gotcha headings in gotchas.md (the section under the main heading "Hex / Metabase migration gotchas — extended catalog") and insert the missing item or shift all headings and internal references to match the corrected numbering.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/core/skills/metabase-to-hex/scripts/build_layout.py`:
- Around line 206-207: The assignment to doc["appLayout"]["tabs"] will KeyError
if doc lacks an "appLayout" key; update the code around build_layout.py where
doc["appLayout"]["tabs"] and doc["appLayout"]["fullWidth"] are set to ensure
doc["appLayout"] exists first (e.g., use doc.setdefault("appLayout", {}) or an
if "appLayout" not in doc: doc["appLayout"] = {} guard) and then assign
layout_tabs and True to the "tabs" and "fullWidth" keys respectively.
In `@plugins/core/skills/metabase-to-hex/scripts/inventory.py`:
- Line 1: The new skill file inventory.py was added but the generated artifacts
(.rules and .agents/skills) are out of sync; run the repo generator to
regenerate and commit the synced artifacts by executing the provided command
(node --run sync-ai-rules), verify that the updated .rules/ and .agents/skills
outputs include the inventory skill, add those files to the commit, and push so
the PR contains the regenerated artifacts alongside inventory.py.
- Around line 90-92: The print formatting crashes when c["display"] can be None;
update the loop over query_cards so the display field is converted to a safe
string before applying the {:8s} format (e.g., use c.get("display") or "" or
str(c.get("display"))), so the f-string in the loop that builds kind and prints
using f"{c['display']:8s}" never receives None; modify the printing expression
in the for c in query_cards block (referencing variables query_cards, c, kind)
to use the safe-display value instead.
In `@plugins/core/skills/metabase-to-hex/SKILL.md`:
- Around line 1-14: The new SKILL.md for metabase-to-hex was added but the
synced artifacts under .rules/ and .agents/skills/ are missing; run the sync
script and commit the generated outputs: execute `node --run sync-ai-rules` from
the repo root to regenerate the metabase-to-hex entries, verify that
corresponding files are created under .rules/ (rule definitions) and
.agents/skills/ (skill metadata), and add/commit those generated artifacts
alongside plugins/core/skills/metabase-to-hex/SKILL.md.
---
Nitpick comments:
In `@plugins/core/skills/metabase-to-hex/references/gotchas.md`:
- Around line 1-6: The gotchas list in "Hex / Metabase migration gotchas —
extended catalog" skips number 8 (entries go 1–7 then 9); either restore the
missing `#8` entry or renumber the subsequent entries so numbering is sequential
and update any cross-references in SKILL.md accordingly; locate the numbered
gotcha headings in gotchas.md (the section under the main heading "Hex /
Metabase migration gotchas — extended catalog") and insert the missing item or
shift all headings and internal references to match the corrected numbering.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 00056eb3-7add-4fa4-bc55-7d90c94a8248
📒 Files selected for processing (9)
plugins/core/skills/metabase-to-hex/SKILL.mdplugins/core/skills/metabase-to-hex/references/cbh_stack.mdplugins/core/skills/metabase-to-hex/references/gotchas.mdplugins/core/skills/metabase-to-hex/references/yaml_schemas.mdplugins/core/skills/metabase-to-hex/scripts/audit_vars.shplugins/core/skills/metabase-to-hex/scripts/build_layout.pyplugins/core/skills/metabase-to-hex/scripts/create_cells.sh.tmplplugins/core/skills/metabase-to-hex/scripts/inventory.pyplugins/core/skills/metabase-to-hex/scripts/rename_cells.py
| doc["appLayout"]["tabs"] = layout_tabs | ||
| doc["appLayout"]["fullWidth"] = True |
There was a problem hiding this comment.
Guard against a missing appLayout key.
If the fresh exported.yaml has no appLayout block (e.g. before the app canvas has been bootstrapped, as the playbook notes), doc["appLayout"]["tabs"] = ... raises a KeyError instead of a clear failure.
🛡️ Proposed guard
- doc["appLayout"]["tabs"] = layout_tabs
- doc["appLayout"]["fullWidth"] = True
+ app_layout = doc.setdefault("appLayout", {})
+ app_layout["tabs"] = layout_tabs
+ app_layout["fullWidth"] = True🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/core/skills/metabase-to-hex/scripts/build_layout.py` around lines 206
- 207, The assignment to doc["appLayout"]["tabs"] will KeyError if doc lacks an
"appLayout" key; update the code around build_layout.py where
doc["appLayout"]["tabs"] and doc["appLayout"]["fullWidth"] are set to ensure
doc["appLayout"] exists first (e.g., use doc.setdefault("appLayout", {}) or an
if "appLayout" not in doc: doc["appLayout"] = {} guard) and then assign
layout_tabs and True to the "tabs" and "fullWidth" keys respectively.
| @@ -0,0 +1,119 @@ | |||
| #!/usr/bin/env python3 | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Regenerate the synced rule/skill artifacts.
This PR adds a new skill under plugins/core/skills/. The generated .rules/ and .agents/skills copies must be regenerated and committed so they stay in sync.
node --run sync-ai-rulesAs per coding guidelines: "When modifying ./plugins/core rules or skills, run node --run sync-ai-rules to auto-generate the .rules/ and .agents/skills versions".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/core/skills/metabase-to-hex/scripts/inventory.py` at line 1, The new
skill file inventory.py was added but the generated artifacts (.rules and
.agents/skills) are out of sync; run the repo generator to regenerate and commit
the synced artifacts by executing the provided command (node --run
sync-ai-rules), verify that the updated .rules/ and .agents/skills outputs
include the inventory skill, add those files to the commit, and push so the PR
contains the regenerated artifacts alongside inventory.py.
| for c in query_cards: | ||
| kind = f"native(len={c['native_sql_len']})" if c["qtype"] == "native" else f"mbql(src_table={c['source_table_id']})" | ||
| print(f" {c['cid']:>6} tab={c['tab_name']:40s} {c['display']:8s} {kind:30s} params={c['param_slugs']} -- {c['name']}") |
There was a problem hiding this comment.
:8s format spec crashes when display is None.
card.get("display") can be None, and f"{None:8s}" raises TypeError: unsupported format string passed to NoneType.__format__, aborting the whole inventory print.
🛡️ Proposed guard
- print(f" {c['cid']:>6} tab={c['tab_name']:40s} {c['display']:8s} {kind:30s} params={c['param_slugs']} -- {c['name']}")
+ print(f" {c['cid']:>6} tab={c['tab_name']:40s} {(c['display'] or ''):8s} {kind:30s} params={c['param_slugs']} -- {c['name']}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for c in query_cards: | |
| kind = f"native(len={c['native_sql_len']})" if c["qtype"] == "native" else f"mbql(src_table={c['source_table_id']})" | |
| print(f" {c['cid']:>6} tab={c['tab_name']:40s} {c['display']:8s} {kind:30s} params={c['param_slugs']} -- {c['name']}") | |
| for c in query_cards: | |
| kind = f"native(len={c['native_sql_len']})" if c["qtype"] == "native" else f"mbql(src_table={c['source_table_id']})" | |
| print(f" {c['cid']:>6} tab={c['tab_name']:40s} {(c['display'] or ''):8s} {kind:30s} params={c['param_slugs']} -- {c['name']}") |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/core/skills/metabase-to-hex/scripts/inventory.py` around lines 90 -
92, The print formatting crashes when c["display"] can be None; update the loop
over query_cards so the display field is converted to a safe string before
applying the {:8s} format (e.g., use c.get("display") or "" or
str(c.get("display"))), so the f-string in the loop that builds kind and prints
using f"{c['display']:8s}" never receives None; modify the printing expression
in the for c in query_cards block (referencing variables query_cards, c, kind)
to use the safe-display value instead.
| --- | ||
| name: metabase-to-hex | ||
| description: > | ||
| Migrate a Metabase dashboard or single card/question to a Hex app at Clipboard Health — extract | ||
| the source structure via the Metabase MCP, rewrite SQL onto core dbt models, scaffold the Hex | ||
| project with the CLI, and finish the Input cells / markdown / appLayout via a YAML round-trip. | ||
| Use this whenever the user asks to migrate, port, rebuild, or recreate a Metabase dashboard or | ||
| card in Hex, asks to make a Hex version of a Metabase question, mentions a Metabase dashboard | ||
| or `/question/` URL alongside Hex, wants to recreate Metabase parameter filtering as Hex Input | ||
| cells, or wants to generalize multiple migrated cards into one parametrized app. Also use when | ||
| the user references a previous migration ("like the WOPs Tool one", "same pattern as the | ||
| Payments Dashboard") and wants the playbook applied to a new dashboard or card. | ||
| allowed-tools: Bash, Read, Edit, Write | ||
| --- |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify if .rules/ or .agents/skills/ contain synced versions of this skill
echo "Checking for synced skill artifacts..."
# Check if sync command exists
if ! grep -q "sync-ai-rules" package.json 2>/dev/null; then
echo "WARNING: sync-ai-rules script not found in package.json"
fi
# Look for generated skill files
fd --type f -e md "metabase-to-hex" .rules/ .agents/ 2>/dev/null || echo "No synced artifacts found for metabase-to-hex skill"
# Check if sync-ai-rules script exists
ls -la scripts/*sync* 2>/dev/null || echo "No sync scripts found"Repository: ClipboardHealth/core-utils
Length of output: 181
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Repo root: $(pwd)"
echo
echo "1) Skill source file:"
ls -la plugins/core/skills/metabase-to-hex/SKILL.md
echo
echo "2) Check whether .rules/ and .agents/skills/ exist:"
ls -la .rules 2>/dev/null || echo "MISSING: .rules"
ls -la .agents 2>/dev/null || echo "MISSING: .agents"
ls -la .agents/skills 2>/dev/null || echo "MISSING: .agents/skills"
echo
echo "3) Find any synced skill artifacts mentioning metabase-to-hex:"
# Search filenames and contents (small, targeted)
echo "--- Filenames under .rules/ and .agents/:"
fd --type f -i "metabase-to-hex" .rules .agents 2>/dev/null || true
echo
echo "--- Content matches for 'name: metabase-to-hex' (limit output):"
rg -n "name:\s*metabase-to-hex" .rules .agents 2>/dev/null | head -n 50 || true
echo
echo "4) Show sync script implementation (for context):"
ls -la scripts/syncPlugins.ts 2>/dev/null || true
sed -n '1,200p' scripts/syncPlugins.ts 2>/dev/null || trueRepository: ClipboardHealth/core-utils
Length of output: 7056
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) package.json scripts (sync-ai-rules):"
cat package.json | rg -n "\"sync-ai-rules\"|\"scripts\"|sync-ai-rules" || true
echo
echo "2) Search for 'metabase-to-hex' across generated artifacts:"
rg -n "metabase-to-hex" .rules .agents 2>/dev/null || echo "No occurrences found in .rules/.agents"
echo
echo "3) Search for 'metabase-to-hex' in source skill only (sanity):"
rg -n "metabase-to-hex" plugins/core/skills/metabase-to-hex/SKILL.md || trueRepository: ClipboardHealth/core-utils
Length of output: 536
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Check directories/files for metabase-to-hex under .agents/skills and .rules:"
ls -la .agents/skills | rg -n "metabase-to-hex" || echo "No .agents/skills entries match metabase-to-hex"
ls -la .rules | rg -n "metabase-to-hex" || echo "No .rules entries match metabase-to-hex"
echo
echo "Find any path containing metabase-to-hex under .agents/ and .rules/:"
find .agents .rules -maxdepth 6 -iname "*metabase-to-hex*" -print || trueRepository: ClipboardHealth/core-utils
Length of output: 305
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Filename match under .agents/.rules for *metabase-to-hex* (no depth limit):"
find .agents .rules -iname "*metabase-to-hex*" -print || trueRepository: ClipboardHealth/core-utils
Length of output: 146
Run node --run sync-ai-rules and commit the synced artifacts for metabase-to-hex.
plugins/core/skills/metabase-to-hex/SKILL.md was added, but there are no metabase-to-hex outputs under .rules/ or .agents/skills/. Regenerate with node --run sync-ai-rules and ensure the corresponding synced entries are present/committed.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plugins/core/skills/metabase-to-hex/SKILL.md` around lines 1 - 14, The new
SKILL.md for metabase-to-hex was added but the synced artifacts under .rules/
and .agents/skills/ are missing; run the sync script and commit the generated
outputs: execute `node --run sync-ai-rules` from the repo root to regenerate the
metabase-to-hex entries, verify that corresponding files are created under
.rules/ (rule definitions) and .agents/skills/ (skill metadata), and add/commit
those generated artifacts alongside
plugins/core/skills/metabase-to-hex/SKILL.md.
- markdown:lint: add code-fence languages (MD040) and table delimiter spacing (MD060); auto-fix blank-line rules (MD031/MD032) - format:check: apply oxfmt formatting - spell:check: add domain terms (SQL table/function names, Hex/Metabase jargon) to cspell.json - regenerate the .agents/skills/metabase-to-hex mirror Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove all references to the Snowflake (Small Warehouse) connection and use `snowflake analytics` (530b70b8-b300-43c9-9b3e-e4b98ded0379) as the default dev/draft connection throughout the skill (SKILL.md, cbh_stack.md, gotchas.md, yaml_schemas.md, create_cells.sh.tmpl) and the .agents mirror. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds a new skill at
plugins/core/skills/metabase-to-hex/for migrating a Metabase dashboard or single card/question to a Hex app at Clipboard Health.The skill covers
Contents
SKILL.md— the playbookreferences/—cbh_stack.md,gotchas.md,yaml_schemas.mdscripts/— helper scripts (inventory.py,build_layout.py,rename_cells.py,audit_vars.sh,create_cells.sh.tmpl)🤖 Generated with Claude Code