@metabase/cli 0.3.1-alpha.support-worktrees.b634907 → 0.3.1-alpha.versioning.9ac5f50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{add-collection-CxzzDG4z.mjs → add-collection-Dmd-uNeU.mjs} +6 -10
- package/dist/{alert-CQ7Az16h.mjs → alert-D1u2MVZj.mjs} +7 -7
- package/dist/{alerts-DmwyyBfW.mjs → alerts-DcBjcfEE.mjs} +7 -8
- package/dist/{append-B0avMkvW.mjs → append-B9Htvmab.mjs} +5 -6
- package/dist/{archive-CMTHh4-w.mjs → archive-B660RguB.mjs} +4 -5
- package/dist/{archive-THcEfy9B.mjs → archive-BNivAYGr.mjs} +5 -6
- package/dist/{archive-DCyeRNfV.mjs → archive-BUoYMkxO.mjs} +4 -5
- package/dist/{archive-BZEu6UfT.mjs → archive-BVmFGFwG.mjs} +6 -7
- package/dist/archive-Bf014rFm.mjs +32 -0
- package/dist/{archive-DFofUIEC.mjs → archive-BmsZFOZY.mjs} +4 -5
- package/dist/archive-CNif6BKy.mjs +32 -0
- package/dist/{archive-BPSNe0Ul.mjs → archive-CgmidYZV.mjs} +4 -5
- package/dist/{archive-Cvrkz8F8.mjs → archive-CvU2z5192.mjs} +5 -6
- package/dist/{archive-BQ50OZ7y.mjs → archive-DhDQIKR_.mjs} +4 -5
- package/dist/{archive-BVblae-p.mjs → archive-bPdDITuY.mjs} +4 -5
- package/dist/{auth-BEEkuu4J.mjs → auth-CefYEPP5.mjs} +5 -5
- package/dist/{body-DxRSAMNC.mjs → body-C7m9q4cm.mjs} +3 -3
- package/dist/{branches-CmWc8NyL.mjs → branches-pz04OjF2.mjs} +4 -8
- package/dist/{cancel-DrQqmxvn.mjs → cancel-CNLnv19e.mjs} +4 -5
- package/dist/cancel-task-DbnxSh7U.mjs +25 -0
- package/dist/card-BRarvKYX.mjs +24 -0
- package/dist/{card-CrBGUkGQ.mjs → card-DZxRmver.mjs} +0 -1
- package/dist/{card-BEeafd4Y.mjs → card-zyUkr2nS.mjs} +1 -1
- package/dist/{cards-M_6X8wCI.mjs → cards-DtYlVoGP.mjs} +5 -6
- package/dist/cli.mjs +566 -170
- package/dist/{client-DYD8WZYy.mjs → client-Bv7Iwdvh.mjs} +285 -269
- package/dist/collection-CKeO8X7U.mjs +20 -0
- package/dist/{collection-CJHqsFKP.mjs → collection-DALwHnbz.mjs} +1 -1
- package/dist/{collection-BxE7OzcQ.mjs → collection-WFdBeyqa.mjs} +4 -7
- package/dist/{collection-namespace-CEoQ7G08.mjs → collection-namespace-CvT0TIZA.mjs} +2 -2
- package/dist/{content-translation-C8MlXPOF.mjs → content-translation-D7POzJJ6.mjs} +3 -3
- package/dist/{create-CoubLR5o.mjs → create-BEE8uvz2.mjs} +9 -6
- package/dist/{create-D0anrINz.mjs → create-Bh2j733n.mjs} +11 -16
- package/dist/{create-BupBEwR2.mjs → create-Bwg-5p08.mjs} +8 -13
- package/dist/{create-ByuJ6T4k.mjs → create-CGPle4nE.mjs} +7 -8
- package/dist/{create-hTc131aX.mjs → create-CGgPnb7L.mjs} +4 -5
- package/dist/{create-CY-SzM66.mjs → create-CLgalJUe.mjs} +12 -17
- package/dist/{create-C2XFfbjx.mjs → create-CN24yp_W.mjs} +6 -7
- package/dist/{create-BLWwN0uw.mjs → create-CuYGZ4gu2.mjs} +5 -6
- package/dist/{create-CJ7Am4Gc.mjs → create-DGHILnnk.mjs} +5 -6
- package/dist/{create-z-oMrlfT.mjs → create-DYd_o9BD.mjs} +5 -9
- package/dist/{create-BqpkCjx4.mjs → create-DhDREiiy.mjs} +4 -5
- package/dist/{create-myI6doga.mjs → create-Di4YvIbK.mjs} +5 -6
- package/dist/{create-ldrghMd1.mjs → create-DnqnjGGf.mjs} +4 -5
- package/dist/{create-C7iooS6W.mjs → create-Ds-DnSBe.mjs} +9 -15
- package/dist/{create-BA_tTDEk.mjs → create-JOXq0ULN.mjs} +5 -6
- package/dist/create-branch-DWcxC30N.mjs +31 -0
- package/dist/{csv-DBNzJiWK.mjs → csv-CUQvcCEk.mjs} +5 -6
- package/dist/{current-task-YzemU0Ic.mjs → current-task-D6P0eL21.mjs} +8 -16
- package/dist/{dashboard-B1mpfCq_.mjs → dashboard-BudI952R.mjs} +10 -10
- package/dist/{db-1tLH3nYI.mjs → db-C7UTd-6P.mjs} +7 -7
- package/dist/{delete-CD_-B4Kq.mjs → delete-DSxqbcFE.mjs} +5 -6
- package/dist/{delete-QNgBV6eS.mjs → delete-DbZZKcYj.mjs} +6 -11
- package/dist/{delete-DjAUp9mk.mjs → delete-Ds-zGh9C.mjs} +5 -6
- package/dist/{delete-eAUB7p-f.mjs → delete-Ud6iliGM.mjs} +6 -11
- package/dist/{delete-CpKH5ia4.mjs → delete-_IHffP-A.mjs} +5 -6
- package/dist/{delete-runtime-b2_ZMSjj.mjs → delete-runtime-BjHL1ryM.mjs} +1 -2
- package/dist/{delete-table-DamlxnSO.mjs → delete-table-DtXH6IN5.mjs} +6 -11
- package/dist/dependencies-CR1dlq-A.mjs +36 -0
- package/dist/dirty-CYxnOnh0.mjs +28 -0
- package/dist/document-BoILnE_1.mjs +19 -0
- package/dist/{download-C4v7u-AV.mjs → download-DPpmmYQe.mjs} +3 -7
- package/dist/{eid-CP35PdEF.mjs → eid-D-BbtWjt.mjs} +4 -6
- package/dist/{events-DmbzKIh_.mjs → events-CJEnn8WE.mjs} +5 -6
- package/dist/{export-i8D6laBG.mjs → export-BOgyuIOQ.mjs} +13 -29
- package/dist/{field-BKn9bt7I.mjs → field-CzHBOPER.mjs} +5 -5
- package/dist/{fields-8_p81BqN.mjs → fields-Bwgkrvus.mjs} +5 -6
- package/dist/get-B89DUSvw.mjs +31 -0
- package/dist/get-BL90QC64.mjs +36 -0
- package/dist/get-BLJSCw53.mjs +31 -0
- package/dist/{get-BBOfshz1.mjs → get-BOLwso0V.mjs} +6 -7
- package/dist/{get-BvW21ujw.mjs → get-BaPadzdM.mjs} +4 -5
- package/dist/{get-vvs0qzzM.mjs → get-BfVCLBqc.mjs} +4 -5
- package/dist/{get-B0g6VMBC.mjs → get-C1ZdOvMm.mjs} +4 -5
- package/dist/{get-N4dOaTsp.mjs → get-CLu4yzMp2.mjs} +5 -6
- package/dist/get-COwdtskS.mjs +27 -0
- package/dist/{get-CPTbySa7.mjs → get-CWfIiXwL.mjs} +4 -5
- package/dist/get-CqQ-pf0q.mjs +89 -0
- package/dist/{get-DnCE7K0y.mjs → get-CvIgxPXV.mjs} +5 -6
- package/dist/{get-vrccOMBk.mjs → get-D4OTJblo.mjs} +4 -5
- package/dist/{get-BbHPFNqr.mjs → get-D8lHwu4-.mjs} +4 -5
- package/dist/{get-CWf46UFu.mjs → get-DVi3a2nm.mjs} +6 -7
- package/dist/{get-DFkbi5L3.mjs → get-DgnYF7LR.mjs} +4 -5
- package/dist/{get-BHGgXqUq.mjs → get-DsKmZfM2.mjs} +4 -5
- package/dist/{get-CAzSP-7o.mjs → get-DyyPiiaB.mjs} +4 -5
- package/dist/{get-Bds6Izxk.mjs → get-Eqq13YY-.mjs} +4 -5
- package/dist/{get-run-4Ng8_awa.mjs → get-run-Iya0Yw9s.mjs} +6 -7
- package/dist/{git-sync-DLzJrdMi.mjs → git-sync-BDnxPrqU.mjs} +3 -22
- package/dist/git-sync-CdN0Maun.mjs +28 -0
- package/dist/{git-sync-LQIVMNxO.mjs → git-sync-DxD_ng48.mjs} +2 -31
- package/dist/{group-YN6jj2AN.mjs → group-CmVCLBDz.mjs} +3 -3
- package/dist/{has-remote-changes-BXPGI9xG.mjs → has-remote-changes-DfJUMP8F.mjs} +7 -18
- package/dist/{import-BoxOkA-G.mjs → import-FEAx-Y5A.mjs} +12 -32
- package/dist/{input-DH9i67x_.mjs → input-DFZ_qGW_.mjs} +1 -1
- package/dist/is-dirty-BsYjBSXG.mjs +32 -0
- package/dist/{items-Cv6iAzrI.mjs → items-D4rstE12.mjs} +10 -18
- package/dist/{key-BEhqIzIQ.mjs → key-BmWundO3.mjs} +1 -1
- package/dist/{library-fhVn1KDC.mjs → library-CmctxHjv.mjs} +1 -1
- package/dist/library-DXB8sm4r.mjs +81 -0
- package/dist/{library-CRaOhJnj.mjs → library-uzyHWBap.mjs} +5 -5
- package/dist/{list-DOaWCx8S.mjs → list-1DkkU82x.mjs} +17 -25
- package/dist/{list-BLJkJp5a.mjs → list-B7tqNV8B.mjs} +4 -5
- package/dist/{list-WSJLnunb.mjs → list-BRpPbvyS.mjs} +4 -5
- package/dist/{list-BBp9XjYs.mjs → list-BXL8HFr_.mjs} +4 -5
- package/dist/{list-L2U1l6R4.mjs → list-Bjj0z5BS.mjs} +6 -7
- package/dist/{list-DhrapAcy.mjs → list-BmMi_wPD.mjs} +5 -6
- package/dist/list-CC1M_n6Z.mjs +28 -0
- package/dist/list-CQy0z7f9.mjs +28 -0
- package/dist/{list-BwkfWtP2.mjs → list-D_zvX0ms.mjs} +4 -5
- package/dist/{list--2T-GUEF.mjs → list-DeNGm9G4.mjs} +5 -6
- package/dist/list-Dgm6TkqR.mjs +38 -0
- package/dist/list-DoTiQc3D.mjs +36 -0
- package/dist/{list-C8J3n8B8.mjs → list-DrS3ePsv.mjs} +4 -5
- package/dist/list-bN0RC14-.mjs +59 -0
- package/dist/{list-oAAgU5uE.mjs → list-ndIl9XqV.mjs} +11 -18
- package/dist/{list-tutXEQRW.mjs → list-sQcA4g05.mjs} +5 -6
- package/dist/{list-9uvk9dIA.mjs → list-squb_ioH.mjs} +4 -5
- package/dist/{list-DOZNpX4b.mjs → list-xMfCeuZc.mjs} +5 -6
- package/dist/{login-DqWRF3Og.mjs → login-D_1-zE4A.mjs} +15 -13
- package/dist/{logout-ChCz1bkf.mjs → logout-DPi2q1Wu.mjs} +3 -5
- package/dist/{measure-C5dIdFj1.mjs → measure-CdA8Nl3Z.mjs} +6 -6
- package/dist/{notification-DVrLkjFT.mjs → notification-Fcq1fIPw.mjs} +1 -1
- package/dist/{parameter-values-Dy4cBs5y.mjs → parameter-values-C6dj6I4g.mjs} +4 -6
- package/dist/{parse-enum-D0Jfm_Bz.mjs → parse-enum-B1t8S194.mjs} +1 -1
- package/dist/{parse-id-DDCn3VXx.mjs → parse-id-DR8aUSdL.mjs} +1 -1
- package/dist/{parse-ref-Wv21Roup.mjs → parse-ref-BJ_Q0tNW.mjs} +3 -7
- package/dist/{path-IYhuzjQV.mjs → path-B96DI8u2.mjs} +5 -6
- package/dist/{poll-75SvT7Zv.mjs → poll-By46YQ5J.mjs} +2 -2
- package/dist/{preflight-HLUVr2Yf.mjs → preflight-Bl1oitm8.mjs} +3 -4
- package/dist/{process-DBOOrmET.mjs → process-CcQM4qPv.mjs} +1 -1
- package/dist/{publish-CMkCSt8i.mjs → publish-BKJYvxif.mjs} +9 -10
- package/dist/{pulse-a-83M4DV.mjs → pulse-DhG6I9mI.mjs} +1 -1
- package/dist/{query-tWQAV9pb.mjs → query-BKSM-pbi.mjs} +9 -11
- package/dist/{query-Bka77J62.mjs → query-qBHjZQc_.mjs} +7 -10
- package/dist/{query-result-E4Q-Gra6.mjs → query-result-DBDwk8TS.mjs} +1 -1
- package/dist/{remove-collection-BV9wRQZD.mjs → remove-collection-BWFW7Rn6.mjs} +6 -10
- package/dist/{render-DHjCcUXn.mjs → render-DmykmrFB.mjs} +11 -8
- package/dist/{replace-mt47dlRV.mjs → replace-BmAqD3zY.mjs} +5 -6
- package/dist/{rescan-values-6cRjcpTs.mjs → rescan-values-BrCLrihF.mjs} +4 -5
- package/dist/{run-DI_pDxji.mjs → run-CtbzjDKY.mjs} +6 -7
- package/dist/{run-BmGmC-GQ.mjs → run-q5Y44Fxj.mjs} +26 -15
- package/dist/{runs-9Fu0mug5.mjs → runs-JFlbezkQ.mjs} +7 -8
- package/dist/{runtime-CNAZ_FuR.mjs → runtime-BQiGgbgZ.mjs} +851 -361
- package/dist/{schema-tables-CLG0mtQb.mjs → schema-tables-Bzx2ShyE.mjs} +5 -6
- package/dist/{schemas-Cm5NWy59.mjs → schemas-ww5mU2AS.mjs} +5 -6
- package/dist/{search-CljYyf2F.mjs → search-J4RwCof-.mjs} +9 -15
- package/dist/{segment-IRzlQggt.mjs → segment-XXTjU0eG.mjs} +6 -6
- package/dist/{selectors-D4iOP5uB.mjs → selectors-BAAZMi43.mjs} +3 -3
- package/dist/{send-D7DBnQbu.mjs → send-BmpDlw9O.mjs} +4 -5
- package/dist/{set-DKN8fuC6.mjs → set-DUWrSza9.mjs} +5 -6
- package/dist/{set-active-CkE0Eiqh.mjs → set-active-BiUlbNI5.mjs} +5 -6
- package/dist/{setting-CN4l8N-b.mjs → setting-B1KBQN3M.mjs} +4 -4
- package/dist/{setup-BpTptmdO.mjs → setup-CVaNVwOd.mjs} +4 -5
- package/dist/{signal-CMd0EFUa.mjs → signal-GhGmuHfx.mjs} +11 -2
- package/dist/{list-CtZAu4im.mjs → skill-list-DTnDhnL5.mjs} +17 -47
- package/dist/{skills-BSAiLI3Z.mjs → skills-BWrAlj9l.mjs} +3 -3
- package/dist/{skills-hVKSOCUf.mjs → skills-DkDsSH5F.mjs} +102 -14
- package/dist/snippet-CG75L2DS.mjs +19 -0
- package/dist/{snippet-BxgvQ09J.mjs → snippet-CyKAgIZl.mjs} +2 -5
- package/dist/{snippet-DecHB4Dn.mjs → snippet-oJLaYW9V.mjs} +1 -1
- package/dist/{stash-DJs6A6BA.mjs → stash-DMm8YF8V.mjs} +7 -12
- package/dist/{status-N_2EaWb7.mjs → status-BzEQjQ_t.mjs} +15 -23
- package/dist/{status-DtwBDRtc.mjs → status-ClWsQD6v.mjs} +22 -48
- package/dist/{subscription-BnGDp1oy.mjs → subscription-CdFn2hre.mjs} +6 -6
- package/dist/{subscriptions-BfFwV__x.mjs → subscriptions-DBda1pE5.mjs} +7 -8
- package/dist/{summary-CHiq-4mz.mjs → summary-B4GPiuqD.mjs} +4 -5
- package/dist/{sync-schema-DhnM-rpm.mjs → sync-schema-DsIM5g2U.mjs} +5 -6
- package/dist/{sync-task-G1K47Nvn.mjs → sync-task-BACcrs0i.mjs} +1 -1
- package/dist/{table-BQaiCSNS.mjs → table-D4Alrrwh.mjs} +5 -5
- package/dist/timeline-DmM0BuX8.mjs +21 -0
- package/dist/{timeline-event-B7H1y8s8.mjs → timeline-event-DWIh3Tdt.mjs} +6 -6
- package/dist/transform-BcV_XlSX.mjs +28 -0
- package/dist/{transform-CiDOJGBW.mjs → transform-Bk0D0nIs.mjs} +2 -2
- package/dist/{transform-BvOEn41C.mjs → transform-DpuG-ON3.mjs} +25 -7
- package/dist/{transform-job-50GZHhKH.mjs → transform-job-AaMZRxAq.mjs} +1 -1
- package/dist/{transform-job-DRrK28IH.mjs → transform-job-CCguL6LP.mjs} +41 -4
- package/dist/transform-job-CjtwBGoM.mjs +22 -0
- package/dist/{transform-tag-jBVd6wXd.mjs → transform-tag-CcElGp3C.mjs} +4 -9
- package/dist/{transform-tag-Dip51YBa.mjs → transform-tag-DJ3_bksm.mjs} +5 -5
- package/dist/{transform-tag-DiXWRCQG.mjs → transform-tag-Dmb4u3-Q.mjs} +1 -1
- package/dist/{transforms-C-jYgS6z.mjs → transforms-Dg2MfB2a.mjs} +7 -8
- package/dist/tree-BQL0f7YX.mjs +26 -0
- package/dist/{unpublish-BokbnLng.mjs → unpublish-DfSvb_Rs.mjs} +4 -8
- package/dist/{update-D9OTkZhw.mjs → update-B-hRR8gW.mjs} +5 -6
- package/dist/{update-CpLEEbiJ.mjs → update-BCgAyfj_.mjs} +8 -9
- package/dist/{update-BCGE5UYC.mjs → update-Bhmli02m.mjs} +6 -7
- package/dist/{update-rkbpH0lF.mjs → update-BxIyFtrX.mjs} +5 -6
- package/dist/{update-AZSXMJqu.mjs → update-CDo0Orvu.mjs} +9 -15
- package/dist/{update-B9DcRSBQ.mjs → update-CKoBDTL7.mjs} +13 -19
- package/dist/{update-CfQoYVTc.mjs → update-CiYxcf8M.mjs} +7 -8
- package/dist/{update-e7lyQPxq.mjs → update-Cr5zHb0D.mjs} +9 -15
- package/dist/{update-CPEU8ZEu.mjs → update-CtDHMxW8.mjs} +6 -7
- package/dist/{update-BBQInyiJ.mjs → update-D1QdfpKR.mjs} +6 -7
- package/dist/{update-C4PbAYgW.mjs → update-D4qdTlLF.mjs} +5 -6
- package/dist/{update-BRXKLeJH.mjs → update-DBGaJDsj.mjs} +5 -6
- package/dist/{update-BErxnZrj.mjs → update-Izqip6jY.mjs} +6 -7
- package/dist/{update-Bc8s1TL1.mjs → update-NZhIjTCf.mjs} +5 -6
- package/dist/{update-dashcard-St-dGcE3.mjs → update-dashcard-D5b971AO.mjs} +5 -6
- package/dist/{update-CKL2FtoX.mjs → update-sYLQIUgh.mjs} +6 -7
- package/dist/{upgrade-CUoRHfVg.mjs → upgrade-CD1xtsIv.mjs} +6 -9
- package/dist/{upload-CD555ui1.mjs → upload-BUd3MG90.mjs} +2 -2
- package/dist/upload-DzGTlldn.mjs +13 -0
- package/dist/{upload-BPd1Uzxc.mjs → upload-akKFxpVA.mjs} +4 -8
- package/dist/{uuid-CFN8LIkP.mjs → uuid-oVdJ62eA.mjs} +3 -5
- package/dist/{validate-BWchyW0V.mjs → validate-CWd6l6KZ.mjs} +1 -1
- package/dist/{validate-query-Chc43ezW.mjs → validate-query-Boi8-cAP.mjs} +2 -3
- package/dist/{values-BL_U-Zdw.mjs → values-DLwZl-P8.mjs} +4 -5
- package/dist/{verify-DnBaRmkI.mjs → verify-CH9Tw8yv.mjs} +3 -18
- package/dist/{wait-flags-DzytMEG8.mjs → wait-flags-DiQ_kRjZ.mjs} +3 -3
- package/dist/{wait-mPoOZxrw.mjs → wait-rfTdQWdi.mjs} +9 -17
- package/dist/{window-DSb1tqSe.mjs → window-BkvrP0gB.mjs} +1 -1
- package/package.json +1 -1
- package/skill-data/core/SKILL.md +24 -16
- package/skill-data/data-workflow/references/building-clean-tables.md +6 -2
- package/skill-data/data-workflow/references/reusable-definitions.md +11 -3
- package/skill-data/document/SKILL.md +4 -1
- package/skill-data/git-sync/SKILL.md +6 -91
- package/skill-data/mbql/SKILL.md +1 -1
- package/skill-data/mbql/references/operators.md +20 -15
- package/skill-data/metadata/SKILL.md +1 -1
- package/skill-data/metadata/references/semantic-types.md +7 -1
- package/skill-data/native-sql/references/template-tags.md +6 -2
- package/skill-data/notification/SKILL.md +7 -1
- package/skill-data/transform/SKILL.md +13 -11
- package/skill-data/visualization/SKILL.md +11 -3
- package/skill-data/visualization/references/settings.md +6 -4
- package/skills/metabase-cli/SKILL.md +1 -1
- package/dist/archive-CqOKKrb2.mjs +0 -38
- package/dist/archive-DCjdICg7.mjs +0 -38
- package/dist/branch-BSeGrtP7.mjs +0 -28
- package/dist/cancel-task-BMQXtjW5.mjs +0 -34
- package/dist/card-RlzLDB2z.mjs +0 -24
- package/dist/collection-Bhe20ckt.mjs +0 -20
- package/dist/create-DwrhcI8r2.mjs +0 -144
- package/dist/create-branch-B3BMpF1g.mjs +0 -49
- package/dist/delete-D_OgiI4v.mjs +0 -86
- package/dist/dependencies-DEx0BsZ3.mjs +0 -41
- package/dist/dirty-dC1-Ud0G.mjs +0 -40
- package/dist/document-DOJbBWLF.mjs +0 -19
- package/dist/export-preflight-B5MvYhm3.mjs +0 -67
- package/dist/get-CNEQK0-9.mjs +0 -81
- package/dist/get-Cfagmy1i.mjs +0 -42
- package/dist/get-DvLuY5Xu.mjs +0 -38
- package/dist/get-DwdMvWXU.mjs +0 -44
- package/dist/get-jV8G90Zy.mjs +0 -42
- package/dist/get-mGEv-kag.mjs +0 -33
- package/dist/git-sync-DjoaNmRM.mjs +0 -29
- package/dist/is-dirty-Cwxq4_gd.mjs +0 -44
- package/dist/library-Cfw6eF35.mjs +0 -19
- package/dist/list-5Iojbr_p.mjs +0 -37
- package/dist/list-BD4onDqO.mjs +0 -37
- package/dist/list-C2yL7-CH.mjs +0 -45
- package/dist/list-CbbKip6U.mjs +0 -32
- package/dist/list-Dg2XeDON.mjs +0 -47
- package/dist/network-error-D6CiOEBw.mjs +0 -431
- package/dist/pin-BuZ_kg-u.mjs +0 -62
- package/dist/predicates-Bkm2IoeX.mjs +0 -170
- package/dist/scope-DsGuWG5w.mjs +0 -11
- package/dist/snippet-LlHz3FdJ.mjs +0 -19
- package/dist/timeline-C2VW0Ph6.mjs +0 -21
- package/dist/transform-DAf0Y02t.mjs +0 -28
- package/dist/transform-job-ntiT5Rrh.mjs +0 -22
- package/dist/tree-DtyJhD54.mjs +0 -36
- package/dist/unpin-DxbXmLtW.mjs +0 -45
- package/dist/upload-Dc3QLhZw.mjs +0 -13
- package/dist/worktree-ChdDlG3Q.mjs +0 -25
- package/dist/worktree-DC0kTxxQ.mjs +0 -20
- package/dist/worktree-xAro1xAB.mjs +0 -24
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { t as defineCommandGroup } from "./group-CmVCLBDz.mjs";
|
|
2
|
+
//#region src/commands/upload/index.ts
|
|
3
|
+
var upload_default = defineCommandGroup({
|
|
4
|
+
name: "upload",
|
|
5
|
+
description: "Upload CSV files into Metabase",
|
|
6
|
+
subCommands: {
|
|
7
|
+
csv: () => import("./csv-CUQvcCEk.mjs").then((m) => m.default),
|
|
8
|
+
append: () => import("./append-B9Htvmab.mjs").then((m) => m.default),
|
|
9
|
+
replace: () => import("./replace-BmAqD3zY.mjs").then((m) => m.default)
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
export { upload_default as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-
|
|
1
|
+
import { I as outputFlags, L as profileFlag, N as connectionFlags, c as renderSummary } from "./cli.mjs";
|
|
2
|
+
import { t as defineMetabaseCommand } from "./runtime-BQiGgbgZ.mjs";
|
|
3
3
|
import { t as ContentTranslationUploadResult } from "./content-translation-BrHOrmj9.mjs";
|
|
4
|
-
import { n as requireUploadFilePath, t as readCsvFile } from "./upload-
|
|
4
|
+
import { n as requireUploadFilePath, t as readCsvFile } from "./upload-BUd3MG90.mjs";
|
|
5
5
|
//#region src/output/views/content-translation.ts
|
|
6
6
|
const contentTranslationUploadView = {
|
|
7
7
|
compactPick: ContentTranslationUploadResult,
|
|
@@ -18,11 +18,7 @@ var upload_default = defineMetabaseCommand({
|
|
|
18
18
|
description: "Replace the complete content translation dictionary from CSV"
|
|
19
19
|
},
|
|
20
20
|
details: "Uploads one complete dictionary and replaces every active content translation on the server. Keep the canonical full CSV in version control and download the current dictionary before replacing it. Metabase accepts dictionaries up to 1.5 MiB.",
|
|
21
|
-
|
|
22
|
-
minVersion: 58,
|
|
23
|
-
tokenFeature: "content_translation"
|
|
24
|
-
},
|
|
25
|
-
worktree: "main-only",
|
|
21
|
+
requires: ["contentTranslation.upload"],
|
|
26
22
|
args: {
|
|
27
23
|
...outputFlags,
|
|
28
24
|
...profileFlag,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { K as parseInteger, t as defineMetabaseCommand } from "./runtime-CNAZ_FuR.mjs";
|
|
1
|
+
import { I as outputFlags, K as ConfigError, l as writeJson, u as writeText } from "./cli.mjs";
|
|
2
|
+
import { nt as parseInteger, t as defineMetabaseCommand } from "./runtime-BQiGgbgZ.mjs";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { randomUUID } from "node:crypto";
|
|
6
5
|
//#region src/commands/uuid.ts
|
|
@@ -16,8 +15,7 @@ var uuid_default = defineMetabaseCommand({
|
|
|
16
15
|
skill: "mbql",
|
|
17
16
|
purpose: "where lib/uuid values are used"
|
|
18
17
|
}],
|
|
19
|
-
|
|
20
|
-
worktree: "any",
|
|
18
|
+
requires: null,
|
|
21
19
|
args: {
|
|
22
20
|
...outputFlags,
|
|
23
21
|
count: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as ConfigError, gt as escapeJsonPointerSegment, h as isPlainObject } from "./cli.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
4
4
|
import addFormats from "ajv-formats";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { i as validateQuery, r as isMbql5Query, t as assertNotLegacyEnvelopeWrappingMbql5 } from "./validate-BWchyW0V.mjs";
|
|
1
|
+
import { K as ConfigError, l as writeJson } from "./cli.mjs";
|
|
2
|
+
import { i as validateQuery, r as isMbql5Query, t as assertNotLegacyEnvelopeWrappingMbql5 } from "./validate-CWd6l6KZ.mjs";
|
|
4
3
|
//#region src/commands/validate-query.ts
|
|
5
4
|
const skipValidateFlag = { "skip-validate": {
|
|
6
5
|
type: "boolean",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as defineMetabaseCommand } from "./runtime-
|
|
3
|
-
import { t as parseId } from "./parse-id-
|
|
1
|
+
import { I as outputFlags, L as profileFlag, N as connectionFlags, c as renderSummary, f as formatScalar } from "./cli.mjs";
|
|
2
|
+
import { t as defineMetabaseCommand } from "./runtime-BQiGgbgZ.mjs";
|
|
3
|
+
import { t as parseId } from "./parse-id-DR8aUSdL.mjs";
|
|
4
4
|
import { s as FieldValues } from "./field-Cr2DPUG9.mjs";
|
|
5
5
|
import { n as fieldValuesView } from "./field-BPsNa-TO.mjs";
|
|
6
6
|
//#region src/commands/field/values.ts
|
|
@@ -9,8 +9,7 @@ var values_default = defineMetabaseCommand({
|
|
|
9
9
|
name: "values",
|
|
10
10
|
description: "Fetch the cached distinct values for a field (FieldValues list)"
|
|
11
11
|
},
|
|
12
|
-
|
|
13
|
-
worktree: "any",
|
|
12
|
+
requires: ["field.values"],
|
|
14
13
|
args: {
|
|
15
14
|
...outputFlags,
|
|
16
15
|
...profileFlag,
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
import { n as createClient } from "./client-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { r as HttpError } from "./network-error-D6CiOEBw.mjs";
|
|
5
|
-
//#region ../client/src/version/probe.ts
|
|
6
|
-
const PROBE_PATH = "/api/session/properties";
|
|
7
|
-
const PROBE_TIMEOUT_MS = 1e4;
|
|
8
|
-
async function probeServer(client, opts = {}) {
|
|
9
|
-
const properties = await client.requestParsed(SessionProperties, PROBE_PATH, {
|
|
10
|
-
timeoutMs: PROBE_TIMEOUT_MS,
|
|
11
|
-
retries: opts.retries ?? 0
|
|
12
|
-
});
|
|
13
|
-
return {
|
|
14
|
-
version: tryParseTag(properties.version.tag),
|
|
15
|
-
tokenFeatures: properties["token-features"] ?? null
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
1
|
+
import { n as createClient } from "./client-Bv7Iwdvh.mjs";
|
|
2
|
+
import { J as MetabaseError, Y as NetworkError, Z as TimeoutError, et as errorMessage } from "./cli.mjs";
|
|
3
|
+
import { $ as probeServer, L as HttpError, O as USER_AGENT } from "./runtime-BQiGgbgZ.mjs";
|
|
19
4
|
//#region src/core/auth/verify.ts
|
|
20
5
|
const VERIFY_TIMEOUT_MS = 15e3;
|
|
21
6
|
async function verifyAndProbe(url, credential, options = {}) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as parseId } from "./parse-id-
|
|
3
|
-
import { n as DEFAULT_TIMEOUT_MS, t as DEFAULT_INTERVAL_MS } from "./poll-
|
|
1
|
+
import { t as interruptSignal } from "./cli.mjs";
|
|
2
|
+
import { t as parseId } from "./parse-id-DR8aUSdL.mjs";
|
|
3
|
+
import { n as DEFAULT_TIMEOUT_MS, t as DEFAULT_INTERVAL_MS } from "./poll-By46YQ5J.mjs";
|
|
4
4
|
//#region src/commands/wait-flags.ts
|
|
5
5
|
const waitScheduleFlags = {
|
|
6
6
|
timeout: {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { n as DEFAULT_TIMEOUT_MS, t as DEFAULT_INTERVAL_MS } from "./poll-
|
|
4
|
-
import { r as parseWaitSchedule } from "./wait-flags-
|
|
5
|
-
import {
|
|
6
|
-
import { a as throwIfFailedTask, i as taskPollOptions, n as formatSyncTask, r as syncTaskIdleView, t as SyncTaskOrIdle } from "./sync-task-
|
|
1
|
+
import { I as outputFlags, L as profileFlag, N as connectionFlags, c as renderSummary } from "./cli.mjs";
|
|
2
|
+
import { t as defineMetabaseCommand } from "./runtime-BQiGgbgZ.mjs";
|
|
3
|
+
import { n as DEFAULT_TIMEOUT_MS, t as DEFAULT_INTERVAL_MS } from "./poll-By46YQ5J.mjs";
|
|
4
|
+
import { r as parseWaitSchedule } from "./wait-flags-DiQ_kRjZ.mjs";
|
|
5
|
+
import { c as syncTaskView } from "./git-sync-DxD_ng48.mjs";
|
|
6
|
+
import { a as throwIfFailedTask, i as taskPollOptions, n as formatSyncTask, r as syncTaskIdleView, t as SyncTaskOrIdle } from "./sync-task-BACcrs0i.mjs";
|
|
7
7
|
//#region src/commands/git-sync/wait.ts
|
|
8
8
|
const WaitResult = SyncTaskOrIdle;
|
|
9
9
|
var wait_default = defineMetabaseCommand({
|
|
@@ -11,17 +11,11 @@ var wait_default = defineMetabaseCommand({
|
|
|
11
11
|
name: "wait",
|
|
12
12
|
description: "Poll the current git-sync task until it reaches a terminal status"
|
|
13
13
|
},
|
|
14
|
-
|
|
15
|
-
minVersion: 60,
|
|
16
|
-
tokenFeature: "remote_sync"
|
|
17
|
-
},
|
|
18
|
-
worktree: "scoped",
|
|
19
|
-
details: WORKTREE_SCOPE_DETAIL,
|
|
14
|
+
requires: ["gitSync.waitForTask"],
|
|
20
15
|
args: {
|
|
21
16
|
...outputFlags,
|
|
22
17
|
...profileFlag,
|
|
23
18
|
...connectionFlags,
|
|
24
|
-
...worktreeFlag,
|
|
25
19
|
timeout: {
|
|
26
20
|
type: "string",
|
|
27
21
|
description: "Polling timeout in ms",
|
|
@@ -35,11 +29,9 @@ var wait_default = defineMetabaseCommand({
|
|
|
35
29
|
},
|
|
36
30
|
outputSchema: WaitResult,
|
|
37
31
|
examples: ["mb git-sync wait", "mb git-sync wait --timeout 300000 --json"],
|
|
38
|
-
async run({ args, ctx, getClient
|
|
32
|
+
async run({ args, ctx, getClient }) {
|
|
39
33
|
const schedule = parseWaitSchedule(args);
|
|
40
|
-
const
|
|
41
|
-
const scope = await getWorktree();
|
|
42
|
-
const final = await mb.gitSync.waitForTask(taskPollOptions(schedule), scopeQuery(scope));
|
|
34
|
+
const final = await (await getClient()).gitSync.waitForTask(taskPollOptions(schedule));
|
|
43
35
|
if (final === null) {
|
|
44
36
|
renderSummary({ status: "idle" }, syncTaskIdleView, "No git-sync task is running.", ctx);
|
|
45
37
|
return;
|
package/package.json
CHANGED
package/skill-data/core/SKILL.md
CHANGED
|
@@ -13,7 +13,7 @@ Top-level command groups (run `mb <group> --help` to discover verbs):
|
|
|
13
13
|
```
|
|
14
14
|
auth | db | table | field | upload | content-translation | query | card | dashboard | snippet | segment | measure | collection | library
|
|
15
15
|
document | timeline | timeline-event | transform | transform-job | transform-tag | alert | subscription | setting
|
|
16
|
-
search | git-sync |
|
|
16
|
+
search | git-sync | setup | eid | uuid | upgrade | skills
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
The conventions below — auth, flags, output, body input — hold across **every** group. Per-command flags and examples live in each command's `--help`; add `--json` for the machine-readable form with the output JSON Schema. A few flows have their own skills (see "Specialized skills"). When a card needs a query, prefer MBQL over native SQL (portable, pre-flight-validated — load `mbql`); fall back to native SQL when MBQL can't express it.
|
|
@@ -47,8 +47,6 @@ Once a name is established, pass `--profile <name>` to **every** subsequent comm
|
|
|
47
47
|
|
|
48
48
|
**`--wait` for async operations.** `transform run`, `git-sync import`, and similar verbs return immediately by default. Pass `--wait` whenever the next step depends on completion — without it you race the operation and see "not ready" / transient connection refusals.
|
|
49
49
|
|
|
50
|
-
**`--worktree <id|branch>` scopes a command to a git-sync worktree** — an isolated checkout of one branch's content in the same instance (admin-only, v64+). Precedence: flag, then `MB_WORKTREE`, then the profile's pin (`mb worktree pin <ref>` / `unpin`). **The pin is a lock, not a default:** flag and env may only re-state it, a different worktree exits 2 — that is how a harness confines an agent to one worktree. Each command's `worktree` policy shows in `--help --json`: `scoped` honors the scope, `any` ignores it and takes no `--worktree`, `main-only` (`transform run`, main-app writes) refuses under one — report that refusal rather than unpinning. Workflow: the `git-sync` skill.
|
|
51
|
-
|
|
52
50
|
**Some "lookup" verbs return JSON envelopes, not bare values.** `mb setting get <key>` returns `{"key": "...", "value": ...}`. Extract before reusing:
|
|
53
51
|
|
|
54
52
|
```bash
|
|
@@ -71,7 +69,7 @@ Every list verb takes `--limit <n>` (items this call returns) and `--offset <n>`
|
|
|
71
69
|
|
|
72
70
|
- **`has_more` decides whether to keep going — never compare counts.** `total` is the server's count on endpoints that report one and `null` on those that don't, so arithmetic over it is not a termination condition.
|
|
73
71
|
- **To continue, pass `next_offset` back as `--offset`.** When `has_more` is true `next_offset` is past the offset you sent, so the loop advances; when false the walk is over and `next_offset` is `null`.
|
|
74
|
-
- **`truncated` means the byte cap cut the output, not that the data ran out.** `has_more`/`next_offset` are recomputed to the cut point, so a capped list resumes like any window. Its `bytes` is what the untruncated answer would have measured, so it sizes the work left rather than the reply you hold. Narrow rows with `--fields` rather than raising `--max-bytes` — the cap counts only what you asked for, so `--fields` buys rows directly. A capped list always returns at least one row; when not even one fits it exits 2 with "the smallest response this list can produce is N bytes, over the M-byte --max-bytes cap; …".
|
|
72
|
+
- **`truncated` means the byte cap cut the output, not that the data ran out.** `has_more`/`next_offset` are recomputed to the cut point, so a capped list resumes like any window. Its `bytes` is what the untruncated answer would have measured, so it sizes the work left rather than the reply you hold. Narrow rows with `--fields` rather than raising `--max-bytes` — a bigger cap spends context on fields you didn't ask for, and the cap counts only what you asked for, so `--fields` buys rows directly. A capped list always returns at least one row; when not even one fits it exits 2 with "the smallest response this list can produce is N bytes, over the M-byte --max-bytes cap; …".
|
|
75
73
|
- `limit` is echoed only when you passed `--limit` — except `mb search`, which defaults to `--limit 20` (an unbounded search is expensive server-side) and so always reports one. On nouns the server doesn't page, one large `--limit` with narrow `--fields` is a single request; many small `--offset` hops are one request each.
|
|
76
74
|
|
|
77
75
|
The whole walk, literally:
|
|
@@ -106,7 +104,7 @@ mb <noun> create --file ./.scratch/body.json --profile <n> --json
|
|
|
106
104
|
|
|
107
105
|
Single-quoted `'EOF'` stops the shell interpolating `$vars` inside the JSON.
|
|
108
106
|
|
|
109
|
-
Write working files to **`./.scratch`** in the current directory (`mkdir -p ./.scratch` first), never `/tmp` — they persist across the session and the user can review them.
|
|
107
|
+
Write working files to **`./.scratch`** in the current directory (`mkdir -p ./.scratch` first), never `/tmp` — better permissions, they persist across the session, and the user can review them.
|
|
110
108
|
|
|
111
109
|
## Discovering commands and schemas
|
|
112
110
|
|
|
@@ -125,27 +123,33 @@ mb transform --help --json | jq -r '.commands[].command' # verbs under "transfo
|
|
|
125
123
|
|
|
126
124
|
## Resource quirks worth memorizing
|
|
127
125
|
|
|
128
|
-
Routine verb shapes (list / get / create / update), every flag, and output schemas live in each command's `--help` (add `--json`). Below is only what help does _not_ tell you: footguns and non-obvious behaviors.
|
|
126
|
+
Routine verb shapes (list / get / create / update), every flag, and output schemas live in each command's `--help` (add `--json` for output schemas). Below is only what help does _not_ tell you: footguns and non-obvious behaviors.
|
|
129
127
|
|
|
130
|
-
- **db traversal: the hydration ladder.** Start with `database get <db-id> --include tables` — the compact table map (id, name, schema, description per table), one call that fits most databases.
|
|
131
|
-
- **table fields.** `table get` never returns fields on its own — pass `--include fields` (compact;
|
|
128
|
+
- **db traversal: the hydration ladder.** Start with `database get <db-id> --include tables` — the compact table map (id, name, schema, description per table), one call that fits most databases. Pick the relevant tables, then `table fields <table-id>` per table (bounded: fields are per-table). `--include tables.fields` is the full rollup — small databases only. Hundreds of tables? Traverse by schema (`database schemas <db-id>` → `database schema-tables <db-id> <schema>`) or look tables up by name (`search <term> --models table --db-id <db-id> --limit 10`). `sync-schema` / `rescan-values` queue async work and return `{status:"ok"}` immediately; `sync-schema --wait` blocks until `initial_sync_status: complete`.
|
|
129
|
+
- **table fields.** `table get` never returns fields on its own — pass `--include fields` (compact; the underlying query_metadata response also carries FK targets and dimensions, visible under `--full`) or use `table fields <id>` (list envelope). `table update` patches table-level metadata only; physical columns aren't editable.
|
|
132
130
|
- **field has no `list`.** Fields are per-table — get them via `table get <id> --include fields`. Never enumerate fields across a whole db (context blow-up). `field summary` is live cardinality `{field_id, count, distincts}`; `field values` is the cached distinct set (`has_more_values: true` ⇒ truncated cache). `field update` patches metadata only (`base_type` isn't editable) — this is where you set a column's `semantic_type` or foreign-key target.
|
|
133
131
|
- **upload (CSV → tables).** `upload csv --file <path>` creates a new table + model (prints `{model_id, table_id}`); `upload append <table-id>` / `upload replace <table-id> --file <path>` add to / overwrite a table **previously created by upload** (columns must match). The destination db+schema is admin-configured, not per-call — check with `mb setting get uploads-settings --json` (`db_id: null` ⇒ uploads off/unconfigured; needs admin to read). `--collection <id|root>` only sets the model's collection. Max 50 MB. Errors: **"The uploads database is not configured."** = no db has uploads enabled; **"Uploads are not enabled."** = the append/replace target isn't an uploaded table.
|
|
134
|
-
|
|
132
|
+
<!-- requires: contentTranslation -->
|
|
133
|
+
- **content-translation.** Admin-only, and separate from Remote Sync. `content-translation download > translations.csv` streams the complete active dictionary; `content-translation upload --file translations.csv` replaces every active translation with the file's contents. Always upload the canonical complete CSV, never a partial patch. An empty dictionary downloads as Metabase's four-row sample dictionary — don't re-upload it as real translations. Metabase limits dictionaries to 1.5 MiB.
|
|
134
|
+
<!-- /requires -->
|
|
135
135
|
- **card.** `dataset_query` is the **flat** `mbql/query` value, not a legacy `{type:"query",query:…}` envelope (→ `mbql`). `--export-format csv|xlsx` streams the raw export (pipe to a file), bypassing the JSON envelope. `archive` is the only delete; unarchive with `update --body '{"archived":false}'`. `visualization_settings` keys are scoped by `display` and aren't pre-flighted — see `visualization`.
|
|
136
|
-
- **dashboard.** Dashcards round-trip through `PUT /api/dashboard/:id` (no per-dashcard endpoint): `update-dashcard <dash-id> <dashcard-id>` patches one safely; `update --body '{"dashcards":[…]}'` replaces the whole set (omitted ids are deleted server-side; negative ids for new cards). Every dashcard must include `card_id`, including existing rows; use `card_id:null` plus a `visualization_settings.virtual_card` block (`{display:"text"|"heading"|"link"|…}`) for non-question cards. `create` accepts the **same** `dashcards` array in its initial body, so lay out the whole dashboard in one call. `create`/`update` pre-flight every positive `card_id` and exit **2** with `{ok:false,errors:[…]}` on a bad ref (non-bypassable). `dashboard get <id>` (or `--full`) hydrates dashcards/tabs; `list` omits them. **The grid is 24 columns wide:** each dashcard's `{col, row, size_x, size_y}` is in grid units — **full-width is `size_x: 24`** (`size_x: 12` is half a row, the usual cause of a half
|
|
137
|
-
- **dashboard parameters (filters).** A dashboard's `parameters` array holds its filter widgets; they're part of the dashboard record, so read them with `dashboard get <id> --fields parameters --json` (no separate verb). **Editing replaces the _whole_ array** (like dashcards), so it's a read-modify-write loop and omitting a parameter deletes it. A parameter only filters a card once it is **mapped** onto that dashcard's `parameter_mappings` — an unmapped parameter is an inert widget. `type` is a **closed enum**; an unlisted value is a hard parse error that echoes the allowed set back. `dashboard parameter-values <id> <parameter-id> [--query <substr>]` fetches a widget's selectable values (`{values, has_more_values}`; `--query` is a case-insensitive substring
|
|
136
|
+
- **dashboard.** Dashcards round-trip through `PUT /api/dashboard/:id` (no per-dashcard endpoint): `update-dashcard <dash-id> <dashcard-id>` patches one safely; `update --body '{"dashcards":[…]}'` replaces the whole set (omitted ids are deleted server-side; negative ids for new cards). Every dashcard must include `card_id`, including existing rows; use `card_id:null` plus a `visualization_settings.virtual_card` block (`{display:"text"|"heading"|"link"|…}`) for non-question cards. `create` accepts the **same** `dashcards` array in its initial body, so lay out the whole dashboard in one call. `create`/`update` pre-flight every positive `card_id` and exit **2** with `{ok:false,errors:[…]}` on a bad ref (non-bypassable). `dashboard get <id>` (or `--full`) hydrates dashcards/tabs; `list` omits them. **The grid is 24 columns wide:** each dashcard's `{col, row, size_x, size_y}` is in grid units — **full-width is `size_x: 24`** (`size_x: 12` is half a row, the usual cause of a card filling only half the width). Keep `col + size_x ≤ 24`, start a full-width stack's `col` at 0, and don't overlap (the server stores collisions as sent — no auto-fix). Layout patterns and per-chart default sizes → the `dashboard` skill; load it before composing any `dashcards` array.
|
|
137
|
+
- **dashboard parameters (filters).** A dashboard's `parameters` array holds its filter widgets; they're part of the dashboard record, so read them with `dashboard get <id> --fields parameters --json` (no separate verb). **Editing replaces the _whole_ array** (like dashcards), so it's a read-modify-write loop and omitting a parameter deletes it. A parameter only filters a card once it is **mapped** onto that dashcard's `parameter_mappings` — an unmapped parameter is an inert widget. `type` is a **closed enum**; an unlisted value is a hard parse error that echoes the full allowed set back to you. `dashboard parameter-values <id> <parameter-id> [--query <substr>]` fetches a widget's selectable values (`{values, has_more_values}`; `--query` is a case-insensitive substring search). Parameter types, ids, mapping targets, and value sources → the `dashboard` skill; load it before authoring a `parameters` array.
|
|
138
138
|
- **alert / subscription are two unrelated systems.** `alert` watches one **card** and fires on a send condition (`/api/notification`: a cron string, `channel/email`-prefixed handlers, typed recipients); `subscription` delivers one **dashboard** on a schedule (`/api/pulse`: structured `schedule_type` + hour/day/frame, bare `email` channels, `{id}|{email}` recipients). The bodies are not interchangeable. Both silently deliver nowhere if the server has no SMTP / Slack app — check `mb setting get 'email-configured?'` (quote it; the `?` is a shell glob) before creating either. Their list-valued fields (`handlers`/`subscriptions`, `channels`/`cards`) **replace wholesale** on update, so adding one recipient is a read-modify-write. `mb card alerts <id>` and `mb dashboard subscriptions <id>` list what's already attached to a card/dashboard; `archive` deactivates rather than deletes. Load the `notification` skill before authoring either body.
|
|
139
139
|
- **snippet `--archived` is a swap, not a union** — list returns _either_ active _or_ archived rows, never both. (Same for `--filter archived` on dashboard/collection.)
|
|
140
140
|
- **segment / measure.** `update` and `archive` require a non-blank `revision_message` (audit-logged); the CLI does not synthesize it on `update`. `archive` defaults to `"Archived via mb CLI"` — override with `--revision-message`. `definition` is a flat MBQL clause (→ `mbql`): segment = a filter, measure = exactly one aggregation.
|
|
141
|
-
- **timeline / timeline-event.** Timelines are collection-scoped event annotations for time-series charts: a timeline's events render only on time-series questions saved in the **same collection** (`collection_id`; null = root) — sub-collections do **not** inherit, and events never draw on dashboard cards, only in the question (and collection) view.
|
|
141
|
+
- **timeline / timeline-event.** Timelines are collection-scoped event annotations for time-series charts: a timeline's events render only on time-series questions saved in the **same collection** (`collection_id`; null = root) — sub-collections do **not** inherit, and events never draw on dashboard cards, only in the question (and collection) view. To annotate a question's chart, create the timeline in that question's collection, then add events; an event only draws when its `timestamp` falls inside the chart's displayed time range. Event `create` requires `timestamp` (ISO 8601), `timezone` (IANA name), `time_matters` (true = the time of day is significant, false = date-only), and `timeline_id` — the API never auto-creates a default timeline (that's UI-only). There is no `timeline-event list`; enumerate with `timeline events <id>` (`--archived` to include archived). Archiving a timeline cascades `archived` to its events; `delete` is a **hard** delete of the timeline and all its events — prefer `archive`.
|
|
142
142
|
- **collection `<ref>`** accepts four forms only — positive int, `root`, `trash`, or a 21-char entity_id; anything else is a client-side `ConfigError`. `collection items` pages the server endpoint, pulling only as far as the output cap can show — read `has_more`/`next_offset` to continue. `collection tree` is **JSON-only** (`--format text` is rejected). A transform collection needs `collection create --namespace transforms`.
|
|
143
143
|
- **setting set** parses the value as **strict JSON**: a string is `'"value"'` (inner quotes), booleans `true`/`false`, numbers bare. Wrong quoting silently errors — confirm with `setting get <key>` after. `setting get --json` works on every value type (wrapping bare-text responses into `{key, value}`).
|
|
144
144
|
- **search vs. list.** For plain enumeration of cards/dashboards/collections use the dedicated `… list` verbs; reach for `search --models <kind>` only for ranking against a query string or a cross-resource lookup.
|
|
145
|
+
<!-- requires: transforms -->
|
|
145
146
|
- **transform.** Iterate with `transform update <id>`, never `delete` + `create` (keeps the row, `entity_id`, materialized table, and YAML filename — avoids `_2` suffixes and noisy git history). `transform run` needs `--wait` (or `--sync`, which also waits for the output table to register and returns `target_table_id`) or you get only `{run_id, final:null}`. (→ `transform`.)
|
|
147
|
+
<!-- /requires -->
|
|
146
148
|
- **setup is one-shot.** `mb setup` walks `/api/setup` for a **fresh** instance only — errors against an already-configured one. Mostly for bootstrapping local / e2e instances.
|
|
147
149
|
- **eid** translates a string entity id → numeric id: `mb eid --model <model> <eid1,eid2> --json`. Entity ids are NanoIDs that can start with `-`, which the positional form misreads as a flag (shell quotes don't help) — for those, use `--body '{"entity_ids":{"card":["-…"]}}'` (the id is a JSON string value, immune to flag parsing).
|
|
148
|
-
|
|
150
|
+
<!-- requires: library -->
|
|
151
|
+
- **library.** The Library is a curated subtree (`library-data` "Data" + `library-metrics` "Metrics" under a `library` root): tables published to **Data** appear first in data pickers and rank up in search; metrics saved to **Metrics** are prioritized in nav, search, and the query builder — it's how you tell people (and agents) "start from these, they're trusted." `library get` shows the Library and its Data/Metrics collection ids; `library create` provisions it (idempotent). `library publish --table-ids/--db-ids/--schemas` publishes tables into Data — it **resolves the Data collection itself and creates the Library if absent** (no collection id to find); each `--schemas` entry is `<db-id>:<schema>` (e.g. `1:public`), not a bare name. `publish` cascades to upstream FK dependencies, `unpublish` to downstream dependents; both need **admin or data-analyst** (Curate alone won't publish) and exit **403** without write **and** query permission on every affected table. Publish status shows on the table: `table get`/`table list` carry `is_published` (`collection_id` under `--full`). Good candidates are finished, analysis-ready tables — clean/combine via transforms first, then publish the polished result. Publishing does not put the Data collection in the git-sync scope: on a remote-sync instance, `mb git-sync add-collection <data-collection-id>` is what makes exports carry the published tables' metadata (see the `git-sync` skill).
|
|
152
|
+
<!-- /requires -->
|
|
149
153
|
- **query / uuid.** `mb query` is the ad-hoc MBQL surface (`--print-schema` → `--dry-run` → run); `mb uuid --count <n>` mints the `lib/uuid` values MBQL clauses need. Both live in `mbql`.
|
|
150
154
|
|
|
151
155
|
## Specialized skills (load on demand)
|
|
@@ -158,12 +162,16 @@ This file is enough for any single-command task. For anything deeper, load the r
|
|
|
158
162
|
- **`dashboard`** — building interactive dashboards: wiring filters (parameters + mappings), linked/cascading filters, cross-filtering, click behavior, series, and tabs. Load beyond a plain card-layout task.
|
|
159
163
|
- **`metadata`** — setting field/table metadata: semantic types, foreign-key targets, dropdown/scan behavior, and column visibility, and the downstream features each unlocks. Load when editing what a column _means_, not its data.
|
|
160
164
|
- **`notification`** — scheduled delivery: question alerts (`mb alert`) and dashboard subscriptions (`mb subscription`). Choosing between them, the two schedule/recipient contracts, channel prerequisites, testing a send.
|
|
165
|
+
<!-- requires: transforms -->
|
|
161
166
|
- **`transform`** — transform body JSON, create + run-with-wait, run inspection, tags, jobs.
|
|
167
|
+
<!-- /requires -->
|
|
162
168
|
- **`document`** — Metabase documents (TipTap body, embedding cards).
|
|
163
|
-
|
|
164
|
-
- **`
|
|
169
|
+
<!-- requires: remoteSync -->
|
|
170
|
+
- **`git-sync`** — round-tripping content to/from a git remote.
|
|
171
|
+
<!-- /requires -->
|
|
172
|
+
- **`data-workflow`** — the guided, end-to-end data workflow: investigate raw data, build clean analysis-ready tables, define reusable segments/measures/metrics, answer questions, build dashboards. **Start here when the user states a goal rather than a single verb** — "make sense of my data", "build a data model", "go from raw data to a dashboard", "be my data analyst", "set up analytics for X". It detects where the data is and routes to the right stage.
|
|
165
173
|
|
|
166
|
-
If a task spans more than one, load each. `mb skills list` enumerates
|
|
174
|
+
If a task spans more than one, load each. `mb skills list` enumerates the skills the profile's server can use, and `mb skills get` prints a skill with the sections that server cannot use left out; `--all` shows everything.
|
|
167
175
|
|
|
168
176
|
## Don't
|
|
169
177
|
|
|
@@ -131,7 +131,7 @@ Then make the links real, not just implied:
|
|
|
131
131
|
- **Wire foreign keys between your tables.** Mark each linking id as a foreign key pointing at the id it references — set the column's type to foreign-key and its target so Metabase itself knows the tables connect and can traverse them.
|
|
132
132
|
- **Graft onto existing clean data** the user approved (step 3 / Phase 1): point the linking id at the existing table's id the same way. Link, don't duplicate.
|
|
133
133
|
|
|
134
|
-
**Set the metadata — a transform's output starts blank, and these tables are
|
|
134
|
+
**Set the metadata — a transform's output starts blank, and these tables are the ones people will start from.** A fresh transform table has no descriptions, raw column names, and untyped columns. You worked it out while investigating; don't leave that knowledge stranded in this chat. Set it on the table so the data explains itself inside Metabase (search, the Question editor, Metabot) and is fit to publish. The mechanics — `mb field update` for semantic types / FK targets / display names, `mb table update` for table descriptions, and the feature each edit unlocks — are in the `metadata` skill; the calls about _what_ to set:
|
|
135
135
|
|
|
136
136
|
- **Semantic types — the highest-value piece.** A column's semantic type is what makes Metabase treat it right: `type/Email`, `type/Currency`/`type/Price`, `type/Category` (turns into a filter dropdown), `type/City`/`type/State`/`type/Country`, `type/CreationTimestamp`, `type/Description`. Set it on every column whose meaning you decoded. A typed column shows money as money, offers a filter dropdown, and lands on the right chart axis for everyone downstream; an untyped one is a guess.
|
|
137
137
|
- **Descriptions.** A one-line description on each table and every non-obvious column.
|
|
@@ -165,7 +165,11 @@ Then report plainly:
|
|
|
165
165
|
|
|
166
166
|
End on that connection map: it's what the user reads to trust the result, and what lets whatever they build next join on the right ids instead of guessing.
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
<!-- requires: library -->
|
|
169
|
+
|
|
170
|
+
These clean tables are exactly what belongs in the **Library** — published tables appear first when anyone picks a data source, so people start from your curated set, not the raw source. If the user wants that, publish the polished tables to the Library (`mb library publish` / `mb library create` mechanics and permissions are in `core`). Defining reusable segments / measures / metrics on top is the **reusable-definitions** stage (`references/reusable-definitions.md` in this skill).
|
|
171
|
+
|
|
172
|
+
<!-- /requires -->
|
|
169
173
|
|
|
170
174
|
---
|
|
171
175
|
|
|
@@ -50,7 +50,9 @@ Two things never bend in any mode: when genuinely unsure, **ask** (the Shared Co
|
|
|
50
50
|
- "Let me add up revenue the same way everywhere, on this table" → a **measure** on the table.
|
|
51
51
|
- "Revenue is an _official company number_ people pull onto dashboards" → a **metric** in a collection, with a default month-by-month view so it charts cleanly. Lean: make it a metric when it's a headline figure the org reuses across many questions/dashboards; keep it a measure when it's a table-local convenience.
|
|
52
52
|
- **Where the metric lives.** Metrics sit in a collection (folder). Lean: put the org's blessed ones in the shared **Library** so they surface prominently; keep experimental ones in a working collection until trusted.
|
|
53
|
-
|
|
53
|
+
<!-- requires: library -->
|
|
54
|
+
- **Publish the official tables to the Library.** The clean, analysis-ready tables your definitions sit on are the org's official starting points — the **Library** is how you mark them as such. Tables published to the Library's **Data** section appear _first_ when anyone picks a data source, nudging people toward your curated tables instead of raw warehouse ones. Lean: publish the wide clean tables you built the semantic layer on; hold back raw or half-built ones. Surface which tables you'd publish and confirm. (Only admins and data analysts can publish — mechanics in `core`.)
|
|
55
|
+
<!-- /requires -->
|
|
54
56
|
- **Default time dimension for a metric.** A monthly default makes it chart nicely on a dashboard, but doesn't lock anyone out of other groupings. Lean: set a sensible default (usually month) for anything headline; leave it off for raw counts that aren't inherently time-series.
|
|
55
57
|
- **How strict a segment is.** "Active" = last 30 vs 90 days is a real business call with no right answer from the data alone. Lean: surface the few reasonable thresholds with how many rows each catches, let the user pick.
|
|
56
58
|
|
|
@@ -101,7 +103,9 @@ Build each agreed definition. The verb mechanics (create/update flags, the `revi
|
|
|
101
103
|
- **Segment** → `mb segment create`. A flat MBQL filter clause on a table.
|
|
102
104
|
- **Measure** → `mb measure create`. **Exactly one** aggregation on a table.
|
|
103
105
|
- **Metric** → `mb card create` with the metric shape (`type: "metric"`) — it lives in a **collection**, carries the aggregation plus an optional default time dimension. Put org-blessed ones in the Library collection.
|
|
106
|
+
<!-- requires: library -->
|
|
104
107
|
- **Publish the official tables** → `mb library create` then `mb library publish` (mechanics in `core`) to move the clean tables your definitions sit on into the Library's **Data** section, so people start from your curated set, not raw warehouse tables.
|
|
108
|
+
<!-- /requires -->
|
|
105
109
|
|
|
106
110
|
Then **verify what the user can't see**, before you hand back:
|
|
107
111
|
|
|
@@ -122,10 +126,14 @@ Then **stop. Hard gate — every mode, no exceptions.** Recap in plain language
|
|
|
122
126
|
>
|
|
123
127
|
> **Metric** (in your **Library**, charts by month):
|
|
124
128
|
> • **Monthly recurring revenue**
|
|
125
|
-
|
|
129
|
+
|
|
130
|
+
<!-- requires: library -->
|
|
131
|
+
|
|
126
132
|
> **Published to the Library** (these now show up first when anyone picks a data source):
|
|
127
133
|
> • **Customers**, **Orders**
|
|
128
|
-
|
|
134
|
+
|
|
135
|
+
<!-- /requires -->
|
|
136
|
+
|
|
129
137
|
> Open any of those tables' Filter or Summarize block in Metabase to see them in place and try one — give it a look before you start building dashboards on top.
|
|
130
138
|
|
|
131
139
|
End on that plain-language map. It's what the user reads to trust the result — and it's what stops a wrong definition from quietly propagating into everything built next.
|
|
@@ -81,7 +81,10 @@ Every node is `{ "type": string, "attrs"?: object, "content"?: [nodes], "text"?:
|
|
|
81
81
|
- **`resizeNode`** — wraps a single `cardEmbed` or `flexContainer` to make it resizable (no `_id`). `attrs: { "height": <px>, "minHeight": <px> }`, `content` is exactly one `cardEmbed`/`flexContainer`.
|
|
82
82
|
- **`flexContainer`** — a horizontal row of 1–3 `cardEmbed` / `supportingText` cells side by side (no `_id`). `attrs.columnWidths` is an array of width percentages.
|
|
83
83
|
- **`supportingText`** — a text column that sits next to a card inside a `flexContainer` (id-bearing); `content` is the usual block nodes (`paragraph`, `heading`, lists, …).
|
|
84
|
-
- **`smartLink`** — an inline reference to a Metabase entity (renders as a live chip). Inline, atomic, no `_id`. `attrs: { "entityId": <id>, "model": <model>, "label": <string|null>, "href": <relative-path> }`. `model` ∈ `card`, `dataset`, `metric`, `dashboard`, `collection`, `table`, `database`, `document`, `transform`, `segment`, `user`, `action`, `indexed-entity
|
|
84
|
+
- **`smartLink`** — an inline reference to a Metabase entity (renders as a live chip). Inline, atomic, no `_id`. `attrs: { "entityId": <id>, "model": <model>, "label": <string|null>, "href": <relative-path> }`. `model` ∈ `card`, `dataset`, `metric`, `dashboard`, `collection`, `table`, `database`, `document`, `transform`, `segment`, `user`, `action`, `indexed-entity`.
|
|
85
|
+
<!-- requires: smartLinkMeasureModel -->
|
|
86
|
+
- `measure` is a valid `model` too.
|
|
87
|
+
<!-- /requires -->
|
|
85
88
|
- **`metabot`** — an inline Metabot prompt block.
|
|
86
89
|
|
|
87
90
|
## Embedding an existing card
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: git-sync
|
|
3
|
-
description: Round-trip Metabase content (cards, dashboards, transforms, snippets, collections, Library-published table/field metadata) between an instance and a git remote via `mb git-sync …` — status, dirty / has-remote-changes checks, import, export (with branch guard), branches, stash, add/remove a collection from sync. Load when the user wants to "import the latest changes", "export to git", "push my changes to the repo", "open a PR with my Metabase changes", "git sync", "dirty check", "stash before pulling", "add a collection to sync", or anything `mb git-sync
|
|
3
|
+
description: Round-trip Metabase content (cards, dashboards, transforms, snippets, collections, Library-published table/field metadata) between an instance and a git remote via `mb git-sync …` — status, dirty / has-remote-changes checks, import, export (with branch guard), branches, stash, add/remove a collection from sync. Load when the user wants to "import the latest changes", "export to git", "push my changes to the repo", "open a PR with my Metabase changes", "git sync", "dirty check", "stash before pulling", "add a collection to sync", or anything `mb git-sync …`.
|
|
4
4
|
allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
|
|
5
|
+
requires: [remoteSync]
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# git-sync (representations ↔ instance)
|
|
@@ -40,7 +41,6 @@ Pulls the configured branch and applies it to the instance. Polls until the task
|
|
|
40
41
|
| `--branch <name>` | Defaults to the `remote-sync-branch` setting; override per-call. |
|
|
41
42
|
| `--no-wait` | Return as soon as the task is queued; combine with `mb git-sync wait` later. |
|
|
42
43
|
| `--force` | **Discards local Metabase-side dirty changes** (lossy). Confirm with the user first. |
|
|
43
|
-
| `--merge` | Three-way merge remote changes instead of failing on divergence. Confirm first. |
|
|
44
44
|
| `--timeout <ms>` | Polling deadline. Default 600 000. |
|
|
45
45
|
| `--interval <ms>` | Polling cadence. Default 2 000. |
|
|
46
46
|
|
|
@@ -63,7 +63,6 @@ Pushes Metabase-side changes back to the configured remote. `-m` is the commit m
|
|
|
63
63
|
| `--branch <name>` | Push to a specific branch instead of the configured one. |
|
|
64
64
|
| `-m, --message <s>` | Commit message. |
|
|
65
65
|
| `--force` | Force-push / overwrite remote. Confirm with the user. |
|
|
66
|
-
| `--merge` | Three-way merge instead of failing on divergence. |
|
|
67
66
|
| `--no-wait` | Don't poll. |
|
|
68
67
|
|
|
69
68
|
Workflow:
|
|
@@ -98,94 +97,6 @@ mb git-sync stash --profile <n> # export current state
|
|
|
98
97
|
|
|
99
98
|
`stash` is the safe move when the instance has team work you don't want to lose, but you need to pivot to a different branch (`import` would discard, `export --force` would overwrite). It exports current state to a fresh branch first.
|
|
100
99
|
|
|
101
|
-
## Worktrees (isolated branch checkouts)
|
|
102
|
-
|
|
103
|
-
A **worktree** is a self-contained checkout of one branch's content inside the same instance. Transforms, transform tags, snippets, `transforms`-namespace collections, the Library, cards, dashboards, and documents are tagged with the worktree's id; tables and fields stay shared with the main app. It is how a chain of transforms gets built, exported, and reviewed as a PR without touching production content. Admin-only, and needs Metabase v64+ with the `remote_sync` feature.
|
|
104
|
-
|
|
105
|
-
Two hard limits, up front:
|
|
106
|
-
|
|
107
|
-
- **A worktree's transforms cannot be run.** `mb transform run` refuses while a worktree scope is in force, and the server rejects the run anyway. There is no workaround to find — run the transform in the main app after the branch is merged and imported, and say so rather than trying to validate the SQL by running it in the worktree.
|
|
108
|
-
- **A worktree is bound to its branch for life.** No branch switching inside one; a different branch means a different worktree.
|
|
109
|
-
|
|
110
|
-
### Where am I? Check before touching import/export
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
mb auth status --profile <n> --json | jq '.worktree' # {id, branch} when the profile is pinned, else null
|
|
114
|
-
mb git-sync status --profile <n> --json | jq '.worktree' # the scope this command ran under
|
|
115
|
-
mb worktree list --profile <n> --json # every worktree on the instance
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
A pinned profile pushes to the worktree's branch; an unpinned one pushes to whatever `remote-sync-branch` points at. Confusing the two is how worktree work lands on the team's tracked branch, so read the pin before the first `export`.
|
|
119
|
-
|
|
120
|
-
### Preconditions before creating one
|
|
121
|
-
|
|
122
|
-
1. **The user named the branch.** Create a worktree only for a branch the user asked you to work on.
|
|
123
|
-
2. **A branch holds at most one worktree.** Check `mb worktree list --json` first; a duplicate fails with the server's `A worktree for branch '<b>' already exists.` — reuse it with `mb worktree pin <branch>` instead.
|
|
124
|
-
3. **A pinned profile is already confined.** `mb worktree create` for any other branch is refused, because a second worktree from a pinned session would escape the pin.
|
|
125
|
-
|
|
126
|
-
### The workflow
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
# 1. Create the worktree and pin the profile to it. Mints the branch on the remote when missing
|
|
130
|
-
# (--no-checkout, so the main app's tracked branch is untouched), then pulls the branch in.
|
|
131
|
-
mb worktree create feat/order-metrics --pin --profile <n> --json
|
|
132
|
-
|
|
133
|
-
# 2. Edit transforms. Scoped commands need no extra flag once the profile is pinned.
|
|
134
|
-
mb transform create --file ./.scratch/transform.json --profile <n> --json
|
|
135
|
-
mb transform list --profile <n> --json # only this worktree's transforms
|
|
136
|
-
mb transform update <id> --file ./.scratch/patch.json --profile <n> --json
|
|
137
|
-
|
|
138
|
-
# 3. Read state before pushing — same rule as the main app.
|
|
139
|
-
mb git-sync status --profile <n> --json # branch, dirty flag, current task, all scoped
|
|
140
|
-
mb git-sync dirty --profile <n> --json # exactly what will be committed
|
|
141
|
-
|
|
142
|
-
# 4. Dry-run the push, read the answer, then push.
|
|
143
|
-
mb git-sync export-preflight --profile <n> --json
|
|
144
|
-
mb git-sync export -m "add order metrics transforms" --profile <n>
|
|
145
|
-
|
|
146
|
-
# 5. Open the PR from the branch with plain git / gh, and let a human review and merge it.
|
|
147
|
-
|
|
148
|
-
# 6. Retire the worktree once the PR is merged. This clears the pin it was holding.
|
|
149
|
-
mb worktree delete feat/order-metrics --profile <n> --json
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
`export-preflight` answers `{has_changes, clean, conflicts, summary: {added, updated, removed}, force_push_casualties: {deleted, overwritten}, reason}`. Read it before every worktree export: `clean: true` with empty `conflicts` is a push that applies as-is; a non-empty `conflicts` or `force_push_casualties` is a conversation with the user, not a `--force`.
|
|
153
|
-
|
|
154
|
-
The main app pulls the merged branch from a **different, unpinned** profile — `git-sync import` into the main app and `transform run` are both main-app operations and a pinned profile refuses them:
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
mb git-sync import --profile <main-app-profile>
|
|
158
|
-
mb transform run <id> --wait --profile <main-app-profile> --json
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Scope precedence and what a pinned profile refuses
|
|
162
|
-
|
|
163
|
-
The scope comes from `--worktree <id|branch>`, else `MB_WORKTREE`, else the profile's pin. **The pin is a lock, not a default:** while it stands, the flag and the env var may only re-state it, and naming a different worktree exits 2 with `profile "<p>" is pinned to worktree <id> (<branch>); refusing --worktree <x>`.
|
|
164
|
-
|
|
165
|
-
Under a scope, a command that changes or runs main-app state refuses before any request and exits 2 — `transform run` / `cancel`, `card` / `library` writes, and the main-app git-sync verbs `stash`, `create-branch`, `add-collection`, `remove-collection`:
|
|
166
|
-
|
|
167
|
-
```
|
|
168
|
-
transform run is not available inside a worktree (scope: worktree 3 (feat/order-metrics) from the profile pin); it changes main-app content. Unpin the profile (`mb worktree unpin`) or drop MB_WORKTREE to run it against the main app.
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Two more refusals belong to the scope:
|
|
172
|
-
|
|
173
|
-
- Fetching a row that lives elsewhere: `transform 12 is not in worktree 3 (feat/order-metrics); refusing to touch main-app content`.
|
|
174
|
-
- `--branch` on `import` / `export` / `export-preflight`: `a worktree is pinned to its branch; drop --branch`.
|
|
175
|
-
|
|
176
|
-
### Confirmations these flags need
|
|
177
|
-
|
|
178
|
-
- `--force` (on `import`, `export`, and `worktree delete`) and `--merge` (on `import` / `export`) are **lossy or history-rewriting** — ask the user first, with `AskUserQuestion`, naming what gets discarded. `export-preflight`'s `force_push_casualties` is the list to show them.
|
|
179
|
-
- `mb worktree delete` refuses a worktree holding unpushed changes: `worktree <id> (<branch>) has unpushed changes; push them with mb git-sync export or pass --force to discard`. Export first, or ask before forcing — the content in a worktree exists nowhere else once it is gone.
|
|
180
|
-
|
|
181
|
-
### Don't (worktrees)
|
|
182
|
-
|
|
183
|
-
- **Don't unpin to reach the main app.** The pin is the isolation boundary a harness put there; `mb worktree unpin` to get past a refusal turns an isolated session into one that can write production content. Report the refusal and what you would need instead.
|
|
184
|
-
- **Don't run a worktree's transforms**, and don't route around the refusal with `mb query`, a native card, or a second profile. Validate the query shape with `--dry-run` (see `mbql`) and run it for real in the main app after the merge.
|
|
185
|
-
- **Don't create worktrees for branches you were not asked to touch.** A worktree checks a whole branch's content into the instance; an unwanted one is content to clean up, not a free experiment.
|
|
186
|
-
- **Don't `git-sync export` from the main app while the work lives in a worktree.** It pushes the main app's state to the tracked branch and the worktree's edits are not in it. Check `.worktree` in `git-sync status` before exporting.
|
|
187
|
-
- **Don't hand-write the branch's YAML in the repo to "help" the PR.** Worktree content round-trips through `export` exactly like main-app content — see the first entry of the general "Don't" list below.
|
|
188
|
-
|
|
189
100
|
## Polling and cancelling
|
|
190
101
|
|
|
191
102
|
```bash
|
|
@@ -220,6 +131,8 @@ mb setting set remote-sync-type '"read-write"' --profile <n>
|
|
|
220
131
|
|
|
221
132
|
**Verifying the result.** `mb git-sync status --profile <n> --json` lists the flagged collections under `synced_collections`, and `mb collection get <id> --json` shows the per-collection `is_remote_synced` flag.
|
|
222
133
|
|
|
134
|
+
<!-- requires: library -->
|
|
135
|
+
|
|
223
136
|
## Published table metadata (Library) and sync scope
|
|
224
137
|
|
|
225
138
|
Table and field metadata — table/field descriptions, semantic types (`type/PK`, `type/FK`), FK targets, plus segments and measures on the table — serializes for **Library-published tables only**, under `databases/<db>/schemas/<schema>/tables/<table>/…` in the repo. Eligibility is two-gated: the table must be published (`mb library publish`), **and** the Library collection holding it must itself carry `is_remote_synced: true`. An ordinary warehouse table, or a transform's target table that isn't published, never serializes — a transform's YAML carries only the transform definition (query, target, description), not the output table's field metadata.
|
|
@@ -234,6 +147,8 @@ mb git-sync stash --new-branch <branch> -m "..." --profile <n> # or create-b
|
|
|
234
147
|
|
|
235
148
|
Flagging the collection records it for the next export, which serializes its current content — including already-published tables and their field metadata. `mb library publish` prints a reminder when the target collection is outside the sync scope on an instance with a configured remote.
|
|
236
149
|
|
|
150
|
+
<!-- /requires -->
|
|
151
|
+
|
|
237
152
|
## Don't (git-sync-specific)
|
|
238
153
|
|
|
239
154
|
- Don't turn instance-side changes into hand-written repo files. When the changes were made against the instance, export them (`stash` / `create-branch` + `export`) and PR the exported branch; reconstructing them as YAML by hand — or pushing files in paths/formats the serializer doesn't own — produces content that never applies on import, and pushing behind Metabase's back races its own sync tasks. Hand-editing YAML belongs to the repo-first workflow, in the serialized layout the repo already uses.
|
package/skill-data/mbql/SKILL.md
CHANGED
|
@@ -122,7 +122,7 @@ No `type:"query"` wrapper, no `query:` nesting. If you wrap the query inside a l
|
|
|
122
122
|
|
|
123
123
|
## Legacy formats you may encounter
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
Queries created long ago may carry a different envelope (sometimes called MBQL 4 / "legacy MBQL"); the `mbql/query` shape above is what the server stores and returns. You won't author the legacy shapes, but you may see them in old content. Anything not `lib/type: "mbql/query"` is sent as-is and normalized server-side — you lose validation, so don't author these:
|
|
126
126
|
|
|
127
127
|
- **Legacy structured** — `{ "type": "query", "database": N, "query": { "source-table": T, … } }`
|
|
128
128
|
- **Flat native** — `{ "type": "native", "database": N, "native": { "query": "SELECT …" } }` — the server accepts it, but author the native stage instead (`native-sql`).
|