@metabase/cli 0.1.15 → 0.1.17

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.
Files changed (217) hide show
  1. package/README.md +69 -32
  2. package/dist/{add-collection-CXhrMjXU.mjs → add-collection-C-t9SQBk.mjs} +5 -5
  3. package/dist/add-collection-Dek6kiRI.mjs +11 -0
  4. package/dist/{archive-BUwiCFnd.mjs → archive-C7dnyzVY.mjs} +9 -7
  5. package/dist/{archive-Blc1dz8Z.mjs → archive-CaoUUTIb.mjs} +8 -7
  6. package/dist/{archive-D-Ovk0-E.mjs → archive-D1FX-sbU.mjs} +7 -6
  7. package/dist/{archive-CQiaCBSj.mjs → archive-DS-KEB4a.mjs} +7 -6
  8. package/dist/{archive-yTvDRQUZ.mjs → archive-LG8u7ec5.mjs} +7 -6
  9. package/dist/{archive-BxGSR7El.mjs → archive-qSOcACQo.mjs} +8 -6
  10. package/dist/{archive-Drt-rWvU.mjs → archive-wNXwIiF0.mjs} +8 -7
  11. package/dist/auth-Kv2MRkRk.mjs +22 -0
  12. package/dist/{body-B9XTTDEu.mjs → body-IcJ5kFtk.mjs} +3 -3
  13. package/dist/{branches-Ct3PK5U3.mjs → branches-BlNCTmFB.mjs} +7 -6
  14. package/dist/{cancel-tST8Bh0w.mjs → cancel-BnveTPNw.mjs} +6 -5
  15. package/dist/{cancel-task-BHnzRQKL.mjs → cancel-task-CSVI8Zgl.mjs} +7 -6
  16. package/dist/{capabilities-BX1rnVuH.mjs → capabilities-N0jo5U7S.mjs} +1 -1
  17. package/dist/card-Bp58WEUF.mjs +26 -0
  18. package/dist/{card-wCPcuKSi.mjs → card-DEmcRlNO.mjs} +6 -5
  19. package/dist/{cards-BySIFsLG.mjs → cards-CMgGA8OZ.mjs} +8 -6
  20. package/dist/cli.mjs +54 -26
  21. package/dist/collection-D8TI20Ir.mjs +23 -0
  22. package/dist/{collection-namespace-D8ohM5gD.mjs → collection-namespace-CsaxEqOb.mjs} +2 -2
  23. package/dist/command-augment-DdZIfx1V.mjs +11 -0
  24. package/dist/{create-HZ-9GMLx.mjs → create-AeWNv0v-.mjs} +9 -8
  25. package/dist/create-B1xfaZJB.mjs +35 -0
  26. package/dist/{create-DxDD6n1d.mjs → create-B6LQutd0.mjs} +17 -12
  27. package/dist/{create-C7FPeJqF.mjs → create-B79M8YpX.mjs} +10 -9
  28. package/dist/{create-DGxZmbxh.mjs → create-Bg_uMu0p.mjs} +9 -8
  29. package/dist/{create-C43RQYgj.mjs → create-BpkWlgoR.mjs} +18 -12
  30. package/dist/{create-DnT1Sayk.mjs → create-C7u3umLj.mjs} +9 -8
  31. package/dist/{create-4mAGsBd0.mjs → create-FZOrCw5k.mjs} +21 -12
  32. package/dist/{create-fIDFkdox.mjs → create-I5Cv-MBa.mjs} +16 -11
  33. package/dist/{create-D3cVDtxM.mjs → create-LHqwcVbS.mjs} +16 -11
  34. package/dist/{create-BDWthCYq.mjs → create-SHKlj0z3.mjs} +9 -8
  35. package/dist/{create-branch-jPE7nW-E.mjs → create-branch-CGyT99Ny.mjs} +7 -6
  36. package/dist/{current-task-rW54KJax.mjs → current-task-C-0hw2Ae.mjs} +7 -6
  37. package/dist/dashboard-C9pQCnX6.mjs +28 -0
  38. package/dist/{dashboard-B4bn3z6t.mjs → dashboard-DOplbKyQ.mjs} +7 -5
  39. package/dist/{database-BmsxuRmO.mjs → database-D9fftP-i.mjs} +1 -1
  40. package/dist/db-DWykmBOh.mjs +28 -0
  41. package/dist/{delete-BWO6uB4P.mjs → delete--NYYN6wv.mjs} +8 -7
  42. package/dist/{delete-CeigtfRI.mjs → delete-Do3nn9sl.mjs} +8 -7
  43. package/dist/{delete-runtime-PzLFavb0.mjs → delete-runtime-B0ha5QR4.mjs} +3 -3
  44. package/dist/{delete-CBwztF6P.mjs → delete-tCVrYjKD.mjs} +8 -7
  45. package/dist/{delete-table-BXzvDEPG.mjs → delete-table-CWSGPw0i.mjs} +8 -7
  46. package/dist/{dependencies-D2N9eqm1.mjs → dependencies-CyFocD8I.mjs} +7 -6
  47. package/dist/{dirty-DoEZRSGB.mjs → dirty-BXM0YJ_a.mjs} +7 -6
  48. package/dist/document-DNDm8_Py.mjs +22 -0
  49. package/dist/{eid-1mROiwJr.mjs → eid-p-zn_1RJ.mjs} +13 -7
  50. package/dist/{error-D5bZ5BUX.mjs → error-5H_tcfL8.mjs} +2 -2
  51. package/dist/{export-Bgv5B4_F.mjs → export-B_8wghyo.mjs} +9 -8
  52. package/dist/field-CFt1-KDR.mjs +21 -0
  53. package/dist/{fields-VA7tXHJz.mjs → fields-BsufL9kv.mjs} +8 -7
  54. package/dist/{get-DAsaor0n.mjs → get-4lufgahL.mjs} +7 -6
  55. package/dist/{get-B8etVxWD.mjs → get-68P-L4ja.mjs} +7 -6
  56. package/dist/{get-qnGGGRTa.mjs → get-B45uYMAs.mjs} +8 -6
  57. package/dist/get-B67pe00Z.mjs +36 -0
  58. package/dist/{get-DvQoDU2m.mjs → get-BJoZkATD.mjs} +7 -6
  59. package/dist/{get-BgIE_YEg.mjs → get-BTKeO4vE.mjs} +7 -6
  60. package/dist/{get-RQFSmnpY.mjs → get-C7mq17-2.mjs} +7 -6
  61. package/dist/{get-CGkhSY5L.mjs → get-CDLa6LiC.mjs} +9 -8
  62. package/dist/{get-D9o38nK5.mjs → get-CPw0ROO4.mjs} +7 -6
  63. package/dist/{get-Wj88mnhn.mjs → get-Cl5Ak73C.mjs} +9 -7
  64. package/dist/{get-CqnCaosn.mjs → get-D3k2JUsa.mjs} +7 -6
  65. package/dist/{get-C-UeGtgW.mjs → get-DTqBuIf3.mjs} +6 -5
  66. package/dist/{get-eUYDNALt.mjs → get-DeLnNVQE.mjs} +8 -7
  67. package/dist/{get-DLRBq8kR.mjs → get-Df_3LCVC.mjs} +7 -6
  68. package/dist/{get-BtAD26gc.mjs → get-DurjkUKJ.mjs} +7 -6
  69. package/dist/{get-run-CATz-XMS.mjs → get-run-Dq4qfGfD.mjs} +7 -6
  70. package/dist/git-sync-ByvjqSiy.mjs +31 -0
  71. package/dist/group-BNE_RiH5.mjs +28 -0
  72. package/dist/{has-remote-changes-B6YEMC90.mjs → has-remote-changes-E-4N_O_t.mjs} +7 -6
  73. package/dist/{import-Bl2Wj9Xf.mjs → import-Dg0j3HCP.mjs} +9 -8
  74. package/dist/{input-BXWgdKiS.mjs → input-7Sj85_K7.mjs} +1 -1
  75. package/dist/is-dirty-D7UMN0mt.mjs +10 -0
  76. package/dist/{is-dirty-D9MoFj0T.mjs → is-dirty-DWw1yBeR.mjs} +4 -4
  77. package/dist/{items-LjtICjvX.mjs → items-CQtt9X4M.mjs} +9 -8
  78. package/dist/{key-C8q5oIr5.mjs → key-bltP32Pm.mjs} +1 -1
  79. package/dist/library-B5AvpACG.mjs +24 -0
  80. package/dist/{list-ChK06rJh.mjs → list-B1uVWy6A.mjs} +8 -6
  81. package/dist/{list-DaJk60dd.mjs → list-BAOTQHst.mjs} +6 -5
  82. package/dist/{list-C410Ptw_.mjs → list-BF-W4jOZ.mjs} +9 -7
  83. package/dist/{list-DMik04Dh.mjs → list-BFVuPodI.mjs} +6 -5
  84. package/dist/{list-DfoNv0gb.mjs → list-BHAWYZ1z.mjs} +6 -5
  85. package/dist/{list-DcjenlTM.mjs → list-BKUvhAs4.mjs} +6 -5
  86. package/dist/{list-Dq86BAMG.mjs → list-BgUWqZa2.mjs} +8 -7
  87. package/dist/{list-CfWblVHJ.mjs → list-C4bALfCs.mjs} +7 -6
  88. package/dist/{list-CoRX8Ruc.mjs → list-C9O2RY5u.mjs} +6 -5
  89. package/dist/{list-cnqPlJgC.mjs → list-CfqpDTna.mjs} +6 -5
  90. package/dist/{list-C6U3Ftg8.mjs → list-CvhVYOVl.mjs} +7 -6
  91. package/dist/{list-B5Q7E2Km.mjs → list-D3TSAqwl.mjs} +6 -5
  92. package/dist/list-D5Gdz8hi.mjs +100 -0
  93. package/dist/{list-Bjp9nd0o.mjs → list-DG0FIhTK.mjs} +6 -5
  94. package/dist/{list-DtrfE0sF.mjs → list-KxQNqp4T.mjs} +8 -7
  95. package/dist/{login-Cn2UtFUt.mjs → login-Bt6j6yBM.mjs} +10 -9
  96. package/dist/{logout-_HXgEmqA.mjs → logout-ANkL02p0.mjs} +6 -5
  97. package/dist/{manifest-DYeLri80.mjs → manifest-BVf8P4bl.mjs} +9 -2
  98. package/dist/measure-CgFwtL1r.mjs +25 -0
  99. package/dist/{metadata-8yqT8OZI.mjs → metadata-ClehtgZj.mjs} +9 -8
  100. package/dist/{metadata-DHODjg1d.mjs → metadata-DplshwI3.mjs} +8 -7
  101. package/dist/{command-augment-CAur0XOQ.mjs → notice-DyVl5aYB.mjs} +1 -11
  102. package/dist/parameter-CiJ4CwWE.mjs +118 -0
  103. package/dist/parameter-values-D4J8Ctu0.mjs +56 -0
  104. package/dist/{parse-enum-BatHQ-Gs.mjs → parse-enum-BL9i_brN.mjs} +1 -1
  105. package/dist/{parse-id-DNPeV0Iu.mjs → parse-id-D4LeTUsP.mjs} +1 -1
  106. package/dist/{parse-ref-CZr1bYIl.mjs → parse-ref-CB_KvF9h.mjs} +1 -1
  107. package/dist/{path-BflajM08.mjs → path-5nQgdvrs.mjs} +6 -5
  108. package/dist/{poll-CYkX02Bm.mjs → poll-BpAJpvb-.mjs} +2 -2
  109. package/dist/{poll-task-oXpl3wzp.mjs → poll-task-TilgciQn.mjs} +2 -2
  110. package/dist/{preflight-BdJr2amA.mjs → preflight-OfHU3Toi.mjs} +4 -4
  111. package/dist/{process-DsGf7Mg5.mjs → process-j8UHMHc2.mjs} +1 -1
  112. package/dist/{prompt-Bc_bHSD0.mjs → prompt-C85xd9HR.mjs} +1 -1
  113. package/dist/publish-DKiqyDwo.mjs +67 -0
  114. package/dist/{query-CxTjguwp.mjs → query-BWJ5h1g3.mjs} +19 -13
  115. package/dist/{query-DWQaN7hO.mjs → query-CQ3xXa9P.mjs} +10 -8
  116. package/dist/{query-result-L5_NrwQR.mjs → query-result-D6mfoVfQ.mjs} +1 -1
  117. package/dist/{remove-collection-BwcFi8Fs.mjs → remove-collection-CO-aMzTO.mjs} +9 -8
  118. package/dist/{rescan-values-B9Qtsd32.mjs → rescan-values-DpL6LGAK.mjs} +9 -8
  119. package/dist/resolve-Dj2MTBkn.mjs +84 -0
  120. package/dist/{run-C-vftXCu.mjs → run-DUcdaZs3.mjs} +6 -5
  121. package/dist/{run-3eFtdI2Z.mjs → run-QYJ-mAaG.mjs} +9 -8
  122. package/dist/{runs-CpRTkn1W.mjs → runs-DgasTnGd.mjs} +8 -7
  123. package/dist/{runtime-C1QgWHM7.mjs → runtime-BJtuxWM8.mjs} +5 -3
  124. package/dist/{schema-tables-rdeupgsu.mjs → schema-tables-ooYjimrV.mjs} +8 -7
  125. package/dist/{schemas-Cr7RjYqV.mjs → schemas-HjFPzsd-.mjs} +6 -5
  126. package/dist/{search-D7Yq2MDu.mjs → search-vaT5EwhG.mjs} +11 -5
  127. package/dist/segment-BPC725mo.mjs +25 -0
  128. package/dist/{selectors-DPc2ZDdd.mjs → selectors-DlmZpo2L.mjs} +4 -4
  129. package/dist/{set-X2N6x7pe.mjs → set-CLHJauzG.mjs} +9 -8
  130. package/dist/{set-active-BoBa3pOw.mjs → set-active-oZOUe9V7.mjs} +6 -5
  131. package/dist/setting-DHYO-W5g.mjs +20 -0
  132. package/dist/{setup-C47WUieB.mjs → setup-D1de5Sbc.mjs} +8 -7
  133. package/dist/{skills-CJ8g8fhQ.mjs → skills-B6gfH0iR.mjs} +1 -1
  134. package/dist/{skills-Po0YPVU5.mjs → skills-NhgVypJ7.mjs} +3 -3
  135. package/dist/snippet-DtLmHr2J.mjs +22 -0
  136. package/dist/{stash-BV4sEp73.mjs → stash-DoRwelwY.mjs} +9 -8
  137. package/dist/{status-BKF9rRnk.mjs → status-BpMOlfsA.mjs} +8 -7
  138. package/dist/{status-Cf8c0NON.mjs → status-CmRgHTrV.mjs} +6 -5
  139. package/dist/{summary-RgLcBcEh.mjs → summary-BEu7pmpq.mjs} +7 -6
  140. package/dist/{sync-schema-DKEel2Sv.mjs → sync-schema-DTUXubMg.mjs} +11 -10
  141. package/dist/table-B1iBqmNu.mjs +22 -0
  142. package/dist/{table-qDD2kApF.mjs → table-DE3i82T_.mjs} +9 -2
  143. package/dist/transform-BuIooRQh.mjs +31 -0
  144. package/dist/transform-job-C3yz0krA.mjs +25 -0
  145. package/dist/transform-tag-CJD6mJUe.mjs +21 -0
  146. package/dist/{transforms-BOQ9CG0l.mjs → transforms-CWvMpLc9.mjs} +7 -6
  147. package/dist/{tree-CF8mscd9.mjs → tree-D18vYSe4.mjs} +6 -5
  148. package/dist/{unpublish-CmaRNjK3.mjs → unpublish-CJbL4ZsC.mjs} +20 -18
  149. package/dist/{update-Kz4kyqY_.mjs → update-7DacwIvi.mjs} +10 -9
  150. package/dist/{update-CgQOSuZt.mjs → update-BjjZIe2W.mjs} +10 -9
  151. package/dist/{update-nwXgVNQa.mjs → update-Bos8nnv0.mjs} +18 -13
  152. package/dist/{update-BXZBEeUp.mjs → update-BvsvyBw9.mjs} +17 -12
  153. package/dist/{update-DQPg0_-d.mjs → update-CSxwZ2us.mjs} +11 -10
  154. package/dist/{update-BuypOaXq.mjs → update-Ck0Kxv8u.mjs} +10 -9
  155. package/dist/{update-B59h7KmS.mjs → update-DV7IY7IQ.mjs} +10 -9
  156. package/dist/{update-DERsb0eO.mjs → update-DhOfrW1j.mjs} +19 -13
  157. package/dist/{update-DR4WkAET.mjs → update-Doia9MP_.mjs} +17 -12
  158. package/dist/{update-rhfPHALN.mjs → update-Dxa_6H2A.mjs} +22 -13
  159. package/dist/{update-dashcard-BJVeSGvO.mjs → update-dashcard-CZUWZhal.mjs} +11 -9
  160. package/dist/{update-DoQpy9SA.mjs → update-mr9todHq.mjs} +10 -9
  161. package/dist/{upgrade-CNrkJF6s.mjs → upgrade-CBW8V9qZ.mjs} +7 -6
  162. package/dist/{uuid-Dpl3ALKq.mjs → uuid-D6JVJ-R1.mjs} +10 -5
  163. package/dist/{validate-VawhJ5Sc.mjs → validate-BqNW4Sk1.mjs} +2 -2
  164. package/dist/{validate-query-CSV-TTnd.mjs → validate-query-CcZVKYPV.mjs} +3 -3
  165. package/dist/{values-DMYpkoEH.mjs → values-DBvuGnnA.mjs} +7 -6
  166. package/dist/{verify-By9ZYzx4.mjs → verify-LIShMNZ2.mjs} +2 -2
  167. package/dist/{wait-BzIAj8lJ.mjs → wait-DUHze3_B.mjs} +8 -7
  168. package/dist/{wait-flags-DQrxnlwv.mjs → wait-flags-Ybpt98PK.mjs} +2 -2
  169. package/package.json +1 -1
  170. package/skill-data/core/SKILL.md +45 -57
  171. package/skill-data/data-workflow/SKILL.md +116 -0
  172. package/skill-data/{data-analysis/SKILL.md → data-workflow/references/answering-questions.md} +7 -13
  173. package/skill-data/{data-transformation/SKILL.md → data-workflow/references/building-clean-tables.md} +46 -48
  174. package/skill-data/{semantic-layer/SKILL.md → data-workflow/references/reusable-definitions.md} +29 -54
  175. package/skill-data/document/SKILL.md +10 -20
  176. package/skill-data/git-sync/SKILL.md +36 -36
  177. package/skill-data/mbql/SKILL.md +3 -15
  178. package/skill-data/mbql/references/operators.md +9 -0
  179. package/skill-data/transform/SKILL.md +26 -42
  180. package/skill-data/visualization/SKILL.md +6 -6
  181. package/skill-data/visualization/references/settings.md +12 -0
  182. package/skills/metabase-cli/SKILL.md +2 -2
  183. package/dist/add-collection-Bnuh0d4j.mjs +0 -10
  184. package/dist/auth-Bkue4Psy.mjs +0 -19
  185. package/dist/card-faWo9ZWU.mjs +0 -20
  186. package/dist/collection-DcRz7fmf.mjs +0 -20
  187. package/dist/dashboard-pXAxJTTx.mjs +0 -21
  188. package/dist/db-CmHHj5eI.mjs +0 -22
  189. package/dist/document-DQIhL75C.mjs +0 -19
  190. package/dist/field-B-UcqFzm.mjs +0 -18
  191. package/dist/git-sync-CwOvcUI2.mjs +0 -28
  192. package/dist/is-dirty-MT0BT4CS.mjs +0 -9
  193. package/dist/list-Cx8JxS2C.mjs +0 -42
  194. package/dist/measure-BIAoqgcS.mjs +0 -19
  195. package/dist/publish-CGUkIqSm.mjs +0 -70
  196. package/dist/segment-BN8sFunv.mjs +0 -19
  197. package/dist/setting-zZjcOPyE.mjs +0 -17
  198. package/dist/snippet-DK0ZA8m5.mjs +0 -19
  199. package/dist/table-COAKXNuj.mjs +0 -21
  200. package/dist/transform-Bto4U82j.mjs +0 -25
  201. package/dist/transform-job-_fW1y2tg.mjs +0 -22
  202. package/dist/transform-tag-C8n1oTr1.mjs +0 -18
  203. package/skill-data/robot-data-engineer/SKILL.md +0 -142
  204. /package/dist/{body-flags-D7q87Btw.mjs → body-flags-DWTTxJpP.mjs} +0 -0
  205. /package/dist/{collection-Deiziuu2.mjs → collection-DrLpA1SO.mjs} +0 -0
  206. /package/dist/{document-qfwR0r63.mjs → document-1W7NRaO_.mjs} +0 -0
  207. /package/dist/{field-E0IBy4Uw.mjs → field-CMY_LWUe.mjs} +0 -0
  208. /package/dist/{measure-JJAdFoqK.mjs → measure-DoJvtCaA.mjs} +0 -0
  209. /package/dist/{paginate-BexjkjbY.mjs → paginate-FVZUxL4J.mjs} +0 -0
  210. /package/dist/{render-CkuFkWlQ.mjs → render-BTKnWL0d.mjs} +0 -0
  211. /package/dist/{revision-message-flag-C7zBeWEt.mjs → revision-message-flag-CHrJgFFx.mjs} +0 -0
  212. /package/dist/{segment-B9SEv9V_.mjs → segment-TXktTCfU.mjs} +0 -0
  213. /package/dist/{setting-i0pugNHl.mjs → setting-m46MUtW5.mjs} +0 -0
  214. /package/dist/{snippet-NNzqlksR.mjs → snippet-CtA2Pkoa.mjs} +0 -0
  215. /package/dist/{transform-n376akp8.mjs → transform-DEF38FWe.mjs} +0 -0
  216. /package/dist/{transform-job-C8lIS-7Q.mjs → transform-job-CtixL4An.mjs} +0 -0
  217. /package/dist/{transform-tag-DB46AhAj.mjs → transform-tag-rsIrckCM.mjs} +0 -0
@@ -6,39 +6,11 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
6
6
 
7
7
  # git-sync (representations ↔ instance)
8
8
 
9
- Metabase content (cards, dashboards, transforms, snippets, collections, …) can live in a git repo as YAML and round-trip in and out of a Metabase instance via the `git-sync` verbs. The instance is configured with a `remote-sync-*` settings block (URL, branch, token, type read-only/read-write); the CLI drives the sync tasks against `/api/ee/remote-sync/*`.
9
+ Metabase content (cards, dashboards, transforms, snippets, collections, …) can live in a git repo as YAML and round-trip in and out of a Metabase instance via the `git-sync` verbs. The instance is configured with a `remote-sync-*` settings block (URL, branch, token, type read-only/read-write); the CLI drives the sync tasks against `/api/ee/remote-sync/*`. Only collections flagged for sync serialize; everything else is local-only.
10
10
 
11
- This skill covers the import/export workflow. The general flag conventions and auth setup live in the `core` skill (`mb skills get core`). To author content YAML by hand: the per-resource clause and settings shapes mirror the API form — query bodies follow the `mbql` skill, `visualization_settings` follow the `viz` skill — except the portable YAML uses **name-based** references (e.g. `[Sample Database, PUBLIC, ORDERS, TOTAL]`, and entity-ids for cross-entity FKs) where the API form uses numeric ids. For the on-disk folder layout, model new files on what the synced repo already contains.
11
+ This skill covers the import/export workflow. Flag conventions and auth setup live in `core` (`mb skills get core`). To author content YAML by hand: the per-resource clause and settings shapes mirror the API form — query bodies follow the `mbql` skill, `visualization_settings` follow the `visualization` skill — except the portable YAML uses **name-based** references (e.g. `[Sample Database, PUBLIC, ORDERS, TOTAL]`, and entity-ids for cross-entity FKs) where the API form uses numeric ids. For the on-disk folder layout, model new files on what the synced repo already contains.
12
12
 
13
- ## Adding / removing a directory (collection) to sync
14
-
15
- The set of directories under sync is governed by which **collections** carry `is_remote_synced: true`. Every collection so flagged serializes to its own folder under `collections/` in the repo; everything outside that set is local-only. The CLI exposes per-collection toggles that route to the underlying bulk endpoint (`PUT /api/ee/remote-sync/settings`):
16
-
17
- ```bash
18
- mb git-sync add-collection <collection-id> --profile <n> --json
19
- mb git-sync remove-collection <collection-id> --profile <n> --json
20
- ```
21
-
22
- `<collection-id>` is a **positive integer**. The bulk endpoint's schema is `pos-int? → boolean`; nano-id / `root` / `trash` refs (which `collection get` accepts) are not supported here. Get the id from `mb collection list --profile <n> --json` first.
23
-
24
- Both verbs return `{ success: true, task_id?: <id> }`. The optional `task_id` only appears when the toggle triggered a follow-up task (e.g., a finalization import after switching to read-only mode); for a normal add/remove in read-write, expect `{ success: true }` and nothing else.
25
-
26
- **Cascade.** A toggle on a parent cascades to every descendant by `location` prefix — `add-collection 4` flips `4` plus every collection nested under it. `remove-collection 4` is the symmetric inverse. There is no per-leaf-only mode.
27
-
28
- **Mode prerequisite.** The server rejects toggles while `remote-sync-type` is `:read-only` (the install default). If `mb git-sync add-collection 12` returns `Metabase returned 400 … Cannot change synced collections when remote-sync-type is read-only.`, switch first with:
29
-
30
- ```bash
31
- mb setting set remote-sync-type '"read-write"' --profile <n>
32
- ```
33
-
34
- (Mind the inner double quotes — `setting set` parses the value as strict JSON.) The server also rejects switching to `:read-only` while the Remote Sync collection is dirty; export or `--force` import first if you're going the other way.
35
-
36
- **Verifying the result.** The CLI's `Collection` schema doesn't yet expose `is_remote_synced`, so `collection get --json` won't show the flag. The pragmatic confirmation paths are:
37
-
38
- - `mb git-sync is-dirty --profile <n> --json` after editing a card in the now-synced collection — a `true` reading proves it's tracked.
39
- - The Metabase Admin UI's Remote Sync page renders the per-collection toggles.
40
-
41
- ## Read state before mutating
13
+ ## Precondition: read state before mutating
42
14
 
43
15
  Always run `status` (or `is-dirty` + `has-remote-changes`) before `import` or `export`. Importing on a dirty instance silently rejects unless you pass `--force`; exporting when the instance is behind the remote pushes a stale state.
44
16
 
@@ -50,7 +22,7 @@ mb git-sync dirty --profile <n> --json # → list the dirty obje
50
22
  mb git-sync current-task --profile <n> --json # → in-flight task (or idle)
51
23
  ```
52
24
 
53
- **Clean up before exporting.** If you've created entities you intend to delete (a failed transform you're going to retry, a card you authored to test a body shape, a draft dashboard) — do the deletes _before_ the first `git-sync export`. Once committed, the cleanup needs a second commit, and the failed entity stays visible in `git log` forever. For the transform case specifically, prefer `transform update <id>` over `delete + create` so iteration never produces "broken-then-fixed" pairs in git history; see the `transform` skill, "Iterating on a failing transform".
25
+ **Clean up before exporting.** If you've created entities you intend to delete (a failed transform you're going to retry, a card you authored to test a body shape, a draft dashboard) — do the deletes _before_ the first `git-sync export`. Once committed, the cleanup needs a second commit, and the failed entity stays visible in `git log` forever. For transforms, prefer `transform update <id>` over delete + create (see the `transform` skill).
54
26
 
55
27
  ## Import (remote → instance)
56
28
 
@@ -71,8 +43,8 @@ Pulls the configured branch and applies it to the instance. Polls until the task
71
43
 
72
44
  Workflow:
73
45
 
74
- 1. `git-sync status` — confirm `dirty: false` (or `--force` is intended).
75
- 2. `git-sync has-remote-changes` — confirm there's actually something to import.
46
+ 1. Read state (above) — confirm `dirty: false` (or `--force` is intended).
47
+ 2. Confirm `has-remote-changes` reports there's actually something to import.
76
48
  3. `git-sync import --branch <branch>` — runs to terminal status by default.
77
49
 
78
50
  ## Export (instance → remote)
@@ -93,7 +65,7 @@ Pushes Metabase-side changes back to the configured remote. `-m` is the commit m
93
65
  Workflow:
94
66
 
95
67
  1. **Branch guard** (below) — confirm the instance isn't tracking `main`/`master`, or that the user has explicitly accepted exporting to it.
96
- 2. `git-sync is-dirty` — confirm there's something to export.
68
+ 2. Read state (above) — confirm `is-dirty` reports there's something to export.
97
69
  3. `git-sync export -m "..."` — pushes and polls.
98
70
  4. (Optional) `git-sync status` — verify `dirty: false` after.
99
71
 
@@ -131,6 +103,34 @@ mb git-sync cancel-task --profile <n> # cancel the in-flight task
131
103
 
132
104
  Use `wait` after `import --no-wait` / `export --no-wait`. Use `cancel-task` if a git-sync task hangs and you want to abandon it.
133
105
 
106
+ ## Adding / removing a directory (collection) to sync
107
+
108
+ The set of directories under sync is governed by which **collections** carry `is_remote_synced: true`. Every collection so flagged serializes to its own folder under `collections/` in the repo; everything outside that set is local-only. The CLI exposes per-collection toggles that route to the underlying bulk endpoint (`PUT /api/ee/remote-sync/settings`):
109
+
110
+ ```bash
111
+ mb git-sync add-collection <collection-id> --profile <n> --json
112
+ mb git-sync remove-collection <collection-id> --profile <n> --json
113
+ ```
114
+
115
+ `<collection-id>` is a **positive integer** (the bulk endpoint's schema is `pos-int? → boolean`; nano-id / `root` / `trash` refs are not supported). Get the id from `collection list` (see `core`).
116
+
117
+ Both verbs return `{ success: true, task_id?: <id> }`. The optional `task_id` only appears when the toggle triggered a follow-up task (e.g., a finalization import after switching to read-only mode); for a normal add/remove in read-write, expect `{ success: true }` and nothing else.
118
+
119
+ **Cascade.** A toggle on a parent cascades to every descendant by `location` prefix — `add-collection 4` flips `4` plus every collection nested under it. `remove-collection 4` is the symmetric inverse. There is no per-leaf-only mode.
120
+
121
+ **Mode prerequisite.** The server rejects toggles while `remote-sync-type` is `:read-only` (the install default). If `mb git-sync add-collection 12` returns `Metabase returned 400 … Cannot change synced collections when remote-sync-type is read-only.`, switch first with:
122
+
123
+ ```bash
124
+ mb setting set remote-sync-type '"read-write"' --profile <n>
125
+ ```
126
+
127
+ (`setting set` parses the value as strict JSON — mind the inner double quotes; see `core`.) The server also rejects switching to `:read-only` while the Remote Sync collection is dirty; export or `--force` import first if you're going the other way.
128
+
129
+ **Verifying the result.** The CLI's `Collection` schema doesn't yet expose `is_remote_synced`, so `collection get --json` won't show the flag. The pragmatic confirmation paths are:
130
+
131
+ - `mb git-sync is-dirty --profile <n> --json` after editing a card in the now-synced collection — a `true` reading proves it's tracked.
132
+ - The Metabase Admin UI's Remote Sync page renders the per-collection toggles.
133
+
134
134
  ## Don't (git-sync-specific)
135
135
 
136
136
  - Don't run `git-sync import --force` or `git-sync export --force` without explicit user confirmation. Both are lossy — `--force` import discards instance-side work, `--force` export overwrites the remote branch.
@@ -138,4 +138,4 @@ Use `wait` after `import --no-wait` / `export --no-wait`. Use `cancel-task` if a
138
138
  - Don't author content directly via `card create` / `transform create` and then assume `git-sync export` will commit it cleanly — the instance and repo can drift if you mix direct API writes with sync-tracked changes. If you do, follow direct writes immediately with `git-sync export -m "..."` to keep them in step.
139
139
  - Don't omit `-m` on `export` if the user wants a meaningful commit message — the default server-generated message is generic.
140
140
  - Don't `git-sync export` to `main`/`master` without explicit user confirmation — sync work is conventionally on a feature branch. See "Branch guard" above.
141
- - Don't reach for `mb setting set` to mark a collection as remote-synced — that endpoint writes single-key settings, not the bulk `collections` map. Use `mb git-sync add-collection <id>` / `mb git-sync remove-collection <id>` (see "Adding / removing a directory (collection) to sync" above), and remember the toggle cascades to descendants.
141
+ - Don't reach for `mb setting set` to mark a collection as remote-synced — that endpoint writes single-key settings, not the bulk `collections` map. Use `mb git-sync add-collection <id>` / `mb git-sync remove-collection <id>` (above), and remember the toggle cascades to descendants.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mbql
3
- description: Author Metabase MBQL 5 query bodies for the `mb` CLI - the only hand-authorable query format. Covers the JSON shape (lib/type mbql/query, flat numeric-id stages), the options-object-always-second clause rule, when lib/uuid is needed (optional - only to reference a clause), the print-schema/dry-run/run loop, where MBQL 5 is consumed (mb query, card dataset_query, transform source.query, measure/segment definition), the flat-vs-legacy-envelope footgun, joins and FK traversal, multi-stage pipelines, naming aggregation columns. Load when building or fixing an MBQL query by hand - "write an MBQL query", "create a card from MBQL", "the dataset_query is wrong", "fix the validation errors", "aggregate and group by", "join two tables", "month-over-month", or any `--dry-run` / `mb query` work.
3
+ description: Author and debug MBQL 5 query bodies for the `mb` CLI — the only hand-authorable query format. Covers the JSON shape (flat numeric-id stages, options-object-second clauses, optional lib/uuid), joins and FK traversal, multi-stage pipelines, aggregation naming, the flat-vs-legacy-envelope footgun, and the print-schema → dry-run → run validation loop. Use when writing or fixing any query body — `mb query`, a card's `dataset_query`, a transform's `source.query`, or a segment/measure `definition` — or when `--dry-run`/run reports validation errors. Triggers — "write an MBQL query", "the dataset_query is wrong", "aggregate and group by", "join two tables", "month-over-month".
4
4
  allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
5
5
  ---
6
6
 
@@ -10,7 +10,7 @@ MBQL 5 is the **only query format you can author by hand** with confidence — i
10
10
 
11
11
  Prefer MBQL over native SQL: portable across warehouse engines and pre-flight-validated. Try it first; fall back to native SQL when MBQL can't express what you need, or when an MBQL body keeps failing server-side and you can't resolve it.
12
12
 
13
- General flag conventions, body-input precedence, and output flags live in the `core` skill (`mb skills get core`).
13
+ General flag conventions, body-input precedence, output flags, `./.scratch`, and `mb uuid` mechanics live in `core` (`mb skills get core`).
14
14
 
15
15
  ## The shape
16
16
 
@@ -64,11 +64,7 @@ Set an explicit `lib/uuid` only when you must **reference a clause from elsewher
64
64
 
65
65
  (`AGG_UUID` is both the aggregation's own `lib/uuid` and the string the ref points at — one value, by string equality. Every other clause omits its UUID. Expression refs work the same way but key off the expression's `lib/expression-name` string, so expressions rarely need an explicit `lib/uuid`.)
66
66
 
67
- When you do need one, **always mint it with `mb uuid` — never write, guess, or copy a UUID yourself.** A hand-authored value is rejected pre-flight as not-a-v4 (`"a1"`, `"uuid-1"`, `"agg-uuid-001"` → `must be a UUID v4 (RFC 4122) — run \`mb uuid\``), or if it looks valid risks colliding with another clause. Only `mb uuid`gives genuine, unique v4s — mint just the few you reference (also covers native template-tag ids and any other`format: "uuid"` slot):
68
-
69
- ```bash
70
- mb uuid --count 2 --json # mint only the clauses you actually reference
71
- ```
67
+ When you do need one, **always mint it with `mb uuid` — never write, guess, or copy a UUID yourself.** A hand-authored value is rejected pre-flight as not-a-v4 (`"a1"`, `"uuid-1"`, `"agg-uuid-001"` → ``must be a UUID v4 (RFC 4122) — run `mb uuid` ``), or if it looks valid risks colliding with another clause. Mint just the few you reference (`mb uuid --count 2 --json`; this also covers native template-tag ids and any other `format: "uuid"` slot).
72
68
 
73
69
  ## Authoring loop: print-schema → dry-run → run
74
70
 
@@ -213,11 +209,3 @@ mb skills path mbql # → the skill dir; then Read references/operator
213
209
  ```
214
210
 
215
211
  `mb query --print-schema` is the exhaustive-but-heavy fallback (the full JSON Schema, ~1600 lines). The cheat-sheet covers the vocabulary; the `--dry-run` loop settles any disagreement.
216
-
217
- ## Don't
218
-
219
- - Don't mint a `lib/uuid` for every clause — they're optional; omit them and the server fills them in. Mint (with `mb uuid`) only the clause you need to reference; never invent, hard-code, or copy a UUID (duplicates are rejected server-side).
220
- - Keep the options object in slot 1 of every clause — `[op, {options}, ...args]`, id last (`["field", {}, 1779]`). The legacy `["field", id, opts]` order (id second) is rejected pre-flight.
221
- - Don't wrap an MBQL 5 body in `{type:"query", query:…}` — `dataset_query` / `source.query` / `definition` is the flat `mbql/query`.
222
- - Don't author MBQL 4 by hand — build it in the UI and pull it with `… get <id> --full --json`.
223
- - Don't skip the `--dry-run` loop on a non-trivial query — it's free and exact.
@@ -11,6 +11,15 @@ when noted: an operator-specific option named in the row, or an explicit `lib/uu
11
11
  you mint to reference the clause. Field refs are numeric: `["field", {…}, <field-id>]`.
12
12
  Everything here passes `mb query --dry-run`; when in doubt, that loop is the authority.
13
13
 
14
+ **Contents**
15
+
16
+ - [Filter operators](#filter-operators) — Logical, Comparison, Null/empty, String match, Temporal, Segment
17
+ - [Aggregation functions](#aggregation-functions) — including naming and the `offset` window function
18
+ - [Expression operators](#expression-operators) — Arithmetic, Math, String, Temporal, Type conversion, Conditional
19
+ - [References (within clauses)](#references-within-clauses) — field, expression, aggregation
20
+ - [Field option: temporal bucketing](#field-option-temporal-bucketing)
21
+ - [Field option: binning](#field-option-binning)
22
+
14
23
  > For relative date filters, prefer **`time-interval`** / **`relative-time-interval`**
15
24
  > (below). `relative-datetime` / `absolute-datetime` literals (e.g. from a UI-built
16
25
  > query) also work.
@@ -8,7 +8,7 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
8
8
 
9
9
  A **transform** persists the result of a query (native SQL or MBQL) to a warehouse table the user can read from cards, dashboards, and other transforms. It runs on a schedule (via `transform-job`) or on-demand (`transform run`).
10
10
 
11
- Flag conventions, body-input precedence, and output flags live in the `core` skill (`mb skills get core`). Deciding _which_ transforms to build — modeling a whole raw database into a set of clean, analysis-ready tables — is the `data-transformation` skill (`mb skills get data-transformation`).
11
+ Flag conventions, body-input precedence, and the `./.scratch` convention live in `core` (`mb skills get core`). Deciding _which_ transforms to build — modeling a whole raw database into clean, analysis-ready tables — is the `data-workflow` skill's build-clean-tables stage (`mb skills get data-workflow`).
12
12
 
13
13
  ## Body shape
14
14
 
@@ -17,14 +17,13 @@ A transform has two halves:
17
17
  - `source` — the query to run (`type: "query"`, with `query.type` of `native` or `mbql`).
18
18
  - `target` — the warehouse destination (`type: "table"`, with `database`, `schema`, `name`).
19
19
 
20
- Native SQL is the simplest source and the easiest to author by hand. MBQL is what the Metabase UI emits and is more verbose; pull a sample with `mb transform get <id> --full --json` if you need its shape.
21
-
22
- For an **MBQL 5** `source.query` (`lib/type: "mbql/query"`), the body shape, the "options object is always second" clause rule, UUID minting, aggregation/order-by refs, naming aggregation output columns, and the `--print-schema` → `--dry-run` validation loop are all in the `mbql` skill — **`mb skills get mbql`**. The MBQL-5 pre-flight on `transform create`/`update` is documented there too (legacy MBQL 4 and native sources skip it). For a transform target, naming your aggregation output columns matters more than usual — a bare `count` / `avg_2` becomes the warehouse column name; see the `mbql` skill's "Naming aggregation output columns".
20
+ Native SQL is the simplest source and the easiest to author by hand. For an **MBQL 5** `source.query` (`lib/type: "mbql/query"`) — the body shape, the options-object-is-always-second clause rule, UUID minting, aggregation/order-by refs, naming aggregation output columns, the `--print-schema` → `--dry-run` validation loop, and the MBQL-5 pre-flight that `transform create`/`update` run (legacy MBQL 4 and native sources skip it) — see `mbql` (**`mb skills get mbql`**). Pull a sample MBQL body with `mb transform get <id> --full --json`. For a transform target, naming aggregation output columns matters more than usual: a bare `count` / `avg_2` becomes the warehouse column name.
23
21
 
24
22
  ## Create + run (native SQL)
25
23
 
24
+ **Keep the SQL formatted.** Author it multi-line in `./.scratch/<name>.sql` and embed with `jq --rawfile` (jq ≥1.6, which JSON-encodes the file so newlines become `\n`). The stored `native.query` is what `mb transform get` and the Metabase editor render — a single-line blob is valid JSON but unreadable when anyone opens the transform. Single-quote the heredoc delimiter (`<<'SQL'`) so the shell leaves `$vars` in the query alone (e.g. Postgres `$1`, `$$`).
25
+
26
26
  ```bash
27
- # Author the SQL formatted — it's what `mb transform get` and the Metabase editor show.
28
27
  cat > ./.scratch/user_counts_by_signup_year.sql <<'SQL'
29
28
  SELECT
30
29
  date_trunc('year', created_at)::date AS signup_year,
@@ -34,7 +33,6 @@ GROUP BY 1
34
33
  ORDER BY 1
35
34
  SQL
36
35
 
37
- # Embed it with jq --rawfile so the newlines survive as \n in valid JSON (don't hand-write the SQL as one line).
38
36
  jq -n --rawfile q ./.scratch/user_counts_by_signup_year.sql \
39
37
  '{ name: "user_counts_by_signup_year",
40
38
  description: "Sample transform: counts users by year of signup",
@@ -46,17 +44,13 @@ TRANSFORM_ID=$(mb transform create --file ./.scratch/transform.json --profile <n
46
44
  mb transform run "$TRANSFORM_ID" --wait --profile <name> --json
47
45
  ```
48
46
 
49
- Notes:
50
-
51
- - `<db-id>` comes from `mb database list --profile <name> --json`. Database ids are per-instance.
52
- - Target `schema` is the schema the result table is written into (e.g. `public`).
53
- - `--wait` on `transform run` polls until status is `succeeded` or `failed`. Without it you only get `{message: "Transform run started", run_id, final: null}` and have to poll yourself.
54
- - `--sync` implies `--wait`, then waits until the run's output table is registered — the run registers it itself, no `db sync-schema` needed — adding `target_table_id` to the envelope. Use it when you'll build MBQL on the output (see "Inspect").
55
- - The `--json` envelope is shape-stable: `{message, run_id, final}` (plus `target_table_id` under `--sync` — a number, or `null` if the table didn't register before the timeout). `final` is `null` when `--wait` is omitted or the run never started, otherwise a full `TransformRun` object with `status` and `message`. On a failed run (`final.status` ∈ {`failed`, `timeout`, `canceled`}) the CLI exits 1 and writes a one-line summary `transform run <id> failed` to stderr; the failure detail lives only in `final.message` on stdout, so `jq -r '.final.message'` is where to look.
56
- - **Keep the SQL formatted.** Author it multi-line in `./.scratch/<name>.sql` and embed with `jq --rawfile` (jq ≥1.6, which JSON-encodes the file so newlines become `\n`). The stored `native.query` is what `mb transform get` and the Metabase editor render — a single-line blob is valid JSON but unreadable when anyone opens the transform. Single-quote the heredoc delimiter (`<<'SQL'`) so the shell leaves `$vars` in the query alone (e.g. Postgres `$1`, `$$`).
57
- - `transform create --json` returns the agent-facing compact projection: `{id, name, description, source_type, target: {type, database, schema, name}, target_db_id}`. Read `target.schema`/`target.name` directly off the create output — no follow-up `transform get` needed to verify where the transform will write.
58
- - If a transform with the same `name` already has a YAML representation on disk under the configured remote-sync repo, `create` mints a `_2` suffix on the exported filename (the new transform gets a fresh `entity_id`; the prior one isn't touched). For "iterate on the same concept" workflows, prefer `transform update <id>` — see "Iterating on a failing transform" below.
59
- - **`collection_id` only accepts a collection in the `:transforms` namespace.** Transforms aren't filed next to cards and dashboards — passing a normal analytics collection id (the kind a dashboard lives in) fails create/update with `collection_id: A Transform can only go in Collections in the :transforms namespace.` Omit `collection_id` to leave the transform uncollected (the common case), or create one with `mb collection create --body '{"name":"…"}' --namespace transforms --json` and pass the returned `id`. Cards and dashboards you build **on top of** the transform's output table go in ordinary collections as usual — so "put the transform and its dashboard in collection X" generally means _X holds the dashboard + cards; the transform stays in the transforms namespace._
47
+ - `<db-id>` comes from `mb database list --profile <name> --json`; ids are per-instance. Target `schema` is the schema the result table is written into (e.g. `public`).
48
+ - `--wait` polls until status is `succeeded` or `failed`. Without it you get only `{message: "Transform run started", run_id, final: null}` and must poll yourself — don't put bare `transform run` in a tight loop; let `--wait` do the polling.
49
+ - `--sync` implies `--wait`, then waits until the run registers its output table (the run registers it itself — no `db sync-schema` needed), adding `target_table_id` to the envelope. Use it when you'll build MBQL on the output (see "Inspect").
50
+ - The `--json` envelope is shape-stable: `{message, run_id, final}` (plus `target_table_id` under `--sync` — a number, or `null` if the table didn't register before the timeout). `final` is `null` when `--wait` is omitted or the run never started, otherwise a full `TransformRun` with `status` and `message`. On a failed run (`final.status` ∈ {`failed`, `timeout`, `canceled`}) the CLI exits 1 and writes a one-line `transform run <id> failed` to stderr; the failure detail lives only in `final.message` on stdout, so `jq -r '.final.message'` is where to look.
51
+ - `transform create --json` returns the agent-facing compact projection: `{id, name, description, source_type, target: {type, database, schema, name}, target_db_id}`. Read `target.schema`/`target.name` directly off it — no follow-up `transform get`.
52
+ - If a transform with the same `name` already has a YAML representation on disk under the configured remote-sync repo, `create` mints a `_2` suffix on the exported filename (the new transform gets a fresh `entity_id`; the prior one isn't touched). For "iterate on the same concept", prefer `transform update <id>` — see "Iterating on a failing transform".
53
+ - **`collection_id` only accepts a collection in the `:transforms` namespace.** Transforms aren't filed next to cards and dashboards — a normal analytics collection id fails create/update with `collection_id: A Transform can only go in Collections in the :transforms namespace.` Omit `collection_id` to leave the transform uncollected (the common case), or provision one with `mb collection create --body '{"name":"…"}' --namespace transforms --json` (see `core`) and pass the returned `id`. Cards and dashboards you build **on top of** the output table go in ordinary collections — so "put the transform and its dashboard in collection X" means _X holds the dashboard + cards; the transform stays in the transforms namespace._
60
54
 
61
55
  ## Inspect
62
56
 
@@ -66,7 +60,7 @@ mb transform get <id> --profile <name> --full --json # full transform i
66
60
  mb transform dependencies <id> --profile <name> --json # upstream transforms this one must run after
67
61
  ```
68
62
 
69
- After a run the table physically exists in the warehouse, but Metabase addresses tables/columns by numeric id, so **MBQL and the UI can't reference a brand-new table until the instance syncs** (native SQL — a native `card` or `mb query` against `<schema>.<name>` — reads it immediately). Run and register in one step with `--sync`.
63
+ After a run the table physically exists in the warehouse, but Metabase addresses tables/columns by numeric id, so **MBQL and the UI can't reference a brand-new table until the instance syncs** (native SQL — a native `card` or `mb query` against `<schema>.<name>` — reads it immediately). Run and register in one step with `--sync`:
70
64
 
71
65
  ```bash
72
66
  TABLE_ID=$(mb transform run <id> --sync --profile <name> --json | jq -r '.target_table_id')
@@ -91,12 +85,10 @@ mb transform get-run <run-id> --profile <name> --json
91
85
  mb transform cancel <id> --profile <name> --json
92
86
  ```
93
87
 
94
- Notes:
95
-
96
88
  - `transform runs` and `transform get-run` parse against the same `TransformRun` schema, so `get-run` returns the same per-run shape as one entry of `runs`. The compact projection is `{id, transform_id, status, run_method, start_time, end_time, message}`. Pass `--full` on `get-run` for the hydrated row including `is_active`, `user_id`, `transform_name`, `transform_entity_id`, `checkpoint_*` fields, and a nested `transform: {id, name, …}` block.
97
- - `transform cancel` takes the **transform** id and 404s with `Endpoint not found — is this a Metabase instance?` if there is no active run. The response shape is `{canceled: true, id: <transform-id>}`.
98
- - For native-SQL transforms, cancel marks the run as `canceling` but does **not** kill the warehouse query mid-flight — the query runs to completion, then the run lands as `canceled` (or stays `succeeded` if the cancel arrived after the writer committed). For Python transforms the worker is interrupted directly. Don't expect cancel to free warehouse resources instantly on long native queries; expect it to flip state and prevent downstream consumers from treating the result as good.
99
- - The `--transform-id` filter on `runs` accepts a single integer; the CLI translates to the server's `transform-ids` query vector. To cross-filter multiple transforms, run `transform runs --json` and `jq` post-hoc.
89
+ - `transform cancel` takes the **transform** id and returns `{canceled: true, id: <transform-id>}`. It 404s with `Endpoint not found — is this a Metabase instance?` if there is no active run.
90
+ - **Cancel semantics differ by source.** For native SQL, cancel marks the run `canceling` but does **not** kill the warehouse query mid-flight — the query runs to completion, then the run lands as `canceled` (or stays `succeeded` if the cancel arrived after the writer committed). For Python transforms the worker is interrupted directly. Don't expect cancel to free warehouse resources instantly on long native queries; expect it to flip state and prevent downstream consumers from treating the result as good.
91
+ - The `--transform-id` filter on `runs` accepts a single integer (translated to the server's `transform-ids` vector). To cross-filter multiple transforms, run `transform runs --json` and `jq` post-hoc.
100
92
 
101
93
  ## Update body: send only writable keys, never round-trip the GET body
102
94
 
@@ -107,7 +99,7 @@ name, description, source, target, run_trigger,
107
99
  tag_ids, collection_id, owner_user_id, owner_email
108
100
  ```
109
101
 
110
- **Don't paste the output of `transform get` into a `transform update` body.** The GET response carries server-side fields (`id`, `entity_id`, `created_at`, `updated_at`, `creator_id`, `last_run`, `target_db_id`, `target_table_id`, `source_type`, `source_database_id`, `source_readable`, `creator`, `owner`, `table`, …) that the PUT endpoint isn't built to handle. Unknown top-level keys flow into `t2/update!` and produce a leaked H2 SQL error like:
102
+ **Never paste the output of `transform get` into a `transform update` body.** The GET response carries server-side fields (`id`, `entity_id`, `created_at`, `updated_at`, `creator_id`, `last_run`, `target_db_id`, `target_table_id`, `source_type`, `source_database_id`, `source_readable`, `creator`, `owner`, `table`, …) that the PUT endpoint isn't built to handle. Unknown top-level keys flow into `t2/update!` and leak a raw H2 SQL error like:
111
103
 
112
104
  ```
113
105
  Column "TAGS" not found; SQL statement:
@@ -116,11 +108,11 @@ UPDATE "TRANSFORM" SET "TAGS" = (), "UPDATED_AT" = NOW() WHERE "ID" = ? [42122-2
116
108
 
117
109
  Three specific footguns:
118
110
 
119
- - **`tags` is not a key on the REST API.** The serdes/YAML representation uses `tags`; the REST contract uses `tag_ids` (an array of integer ids). If you pulled a YAML representation and want to PUT it, translate `tags: [...]` → `tag_ids: [...]` first (or omit it entirely if you're not changing tag membership).
111
+ - **`tags` is not a REST key.** The serdes/YAML representation uses `tags`; the REST contract uses `tag_ids` (an array of integer ids). If you pulled a YAML representation and want to PUT it, translate `tags: [...]` → `tag_ids: [...]` first (or omit it if you're not changing tag membership).
120
112
  - **`source_type`, `target_db_id`, `target_table_id`, `entity_id`** are derived/computed by the server. They appear in GET responses for the agent's benefit; the server doesn't accept them on update.
121
- - **`collection_id` must be a `:transforms`-namespace collection** — a regular card/dashboard collection id is rejected with `A Transform can only go in Collections in the :transforms namespace.` Omit it unless you have one (see the create notes above). Round-tripping the existing value is safe; setting it to an ordinary collection is what fails.
113
+ - **`collection_id` must be a `:transforms`-namespace collection** — a regular card/dashboard collection id is rejected with `A Transform can only go in Collections in the :transforms namespace.` Round-tripping the existing value is safe; setting it to an ordinary collection is what fails.
122
114
 
123
- Right shape — patch only what changes:
115
+ Patch only what changes:
124
116
 
125
117
  ```bash
126
118
  # Rename only:
@@ -140,7 +132,7 @@ mb transform update <id> --file ./.scratch/patch.json --profile <name> --json
140
132
  mb transform update <id> --body '{"tag_ids":[1,3]}' --profile <name> --json
141
133
  ```
142
134
 
143
- `tag_ids` are the integer ids of **transform tags** — discover and manage them with the `transform-tag` group: `mb transform-tag list --json` (find ids; the four built-ins `hourly`/`daily`/`weekly`/`monthly` are seeded), `mb transform-tag create --body '{"name":"nightly"}' --json`, `mb transform-tag update <id>`, `mb transform-tag delete <id>`. Tags are also how a `transform-job` selects what to run — a job executes every transform carrying one of the job's tags (see "Transform jobs" below).
135
+ `tag_ids` are the integer ids of **transform tags** — manage them with the `transform-tag` group: `mb transform-tag list --json` (find ids; the four built-ins `hourly`/`daily`/`weekly`/`monthly` are seeded), `mb transform-tag create --body '{"name":"nightly"}' --json`, `mb transform-tag update <id>`, `mb transform-tag delete <id>`. Tags are also how a `transform-job` selects what to run — a job executes every transform carrying one of the job's tags (see "Transform jobs").
144
136
 
145
137
  If you really must round-trip, project to the writable subset:
146
138
 
@@ -153,13 +145,11 @@ mb transform get <id> --full --profile <name> --json \
153
145
 
154
146
  ## Iterating on a failing transform
155
147
 
156
- When `transform run` fails and you want to retry with a fixed body, **prefer `transform update <id> --file body.json` over `transform delete <id>` + `transform create`.** Update keeps the same row, the same `entity_id`, the same materialized table, and the same on-disk YAML filename:
148
+ When `transform run` fails and you want to retry with a fixed body, **prefer `transform update <id> --file body.json` over `transform delete <id>` + `transform create`.** Update keeps the same row, `entity_id`, materialized table, and on-disk YAML filename:
157
149
 
158
150
  - `git-sync export` produces **one** clean commit containing only the fix, instead of "broken transform" + "remove broken transform" landing as two commits in `git log`.
159
- - You don't have to chase `_2` suffixes minted when two YAMLs share a `name` on disk (see the `transform create` notes above).
160
- - The materialized output table either updates in place or, if the SELECT shape changed incompatibly, errors loudly on the next run rather than landing in a parallel `..._2` table the agent has to clean up. (`transform delete-table <id>` resets the column shape if you need a clean slate.)
161
-
162
- Recipe:
151
+ - You don't chase `_2` suffixes minted when two YAMLs share a `name` on disk.
152
+ - The materialized output table either updates in place or, if the SELECT shape changed incompatibly, errors loudly on the next run rather than landing in a parallel `..._2` table you have to clean up. (`transform delete-table <id>` resets the column shape for a clean slate.)
163
153
 
164
154
  ```bash
165
155
  # 1. Try once
@@ -180,7 +170,7 @@ mb transform update "$ID" --file ./.scratch/source-patch.json --profile <n> --js
180
170
  mb transform run "$ID" --wait --profile <n> --json # → succeeded
181
171
  ```
182
172
 
183
- If you really must `create + delete` instead, do the `delete` **before** the first `git-sync export` so the failed entity never lands in git history. Order matters: agents reflex to "export to checkpoint progress," but for transforms an export of a soft-failed state is mostly noise that needs a follow-up cleanup commit. See the `git-sync` skill, "Read state before mutating" for the ordering rule.
173
+ If you really must `create + delete` instead, do the `delete` **before** the first `git-sync export` so the failed entity never lands in git history — an export of a soft-failed state is noise that needs a follow-up cleanup commit. See `git-sync`, "Read state before mutating", for the ordering rule.
184
174
 
185
175
  ## Drop the materialized table (keep the transform)
186
176
 
@@ -188,7 +178,7 @@ If you really must `create + delete` instead, do the `delete` **before** the fir
188
178
  mb transform delete-table <id> --yes --profile <name>
189
179
  ```
190
180
 
191
- Useful when you've changed the SELECT and want a fresh `CREATE TABLE` on the next run. **`--yes` is required** in non-interactive contexts; without it the command exits with `--yes required to delete non-interactively`.
181
+ Useful when you've changed the SELECT and want a fresh `CREATE TABLE` on the next run. **`--yes` is required** non-interactively; without it the command exits with `refusing to delete <id> without confirmation — pass --yes to proceed non-interactively`.
192
182
 
193
183
  ## Delete the transform
194
184
 
@@ -196,7 +186,7 @@ Useful when you've changed the SELECT and want a fresh `CREATE TABLE` on the nex
196
186
  mb transform delete <id> --yes --profile <name>
197
187
  ```
198
188
 
199
- Removes the definition. Whether the materialized table is dropped depends on the server — check with `mb table list --db-id <db-id> --profile <name> --json` if it matters. Same `--yes` rule as `delete-table`.
189
+ Removes the definition. Whether the materialized table is dropped depends on the server — check with `mb table list --db-id <db-id> --profile <name> --json` if it matters. Same `--yes` rule and message as `delete-table`.
200
190
 
201
191
  ## Transform jobs (schedules)
202
192
 
@@ -212,9 +202,3 @@ mb transform-job set-active false --profile <name> --json # disable every job a
212
202
  ```
213
203
 
214
204
  `transform-job run` is fire-and-forget — the server returns `{message, job_run_id}` immediately, with no per-job-run polling (no `--wait`). Most ad-hoc agent work is one-off `transform run`, not job authoring.
215
-
216
- ## Don't (transform-specific)
217
-
218
- - Don't put `transform run` calls in tight polling loops — pass `--wait` and let the CLI handle the polling. Manual loops without `--wait` will hammer the server.
219
- - Don't author MBQL 4 (the legacy nested `{ type: "query", query: {...} }` shape) by hand — pull a sample with `mb transform get <id> --full --json`. MBQL 5 (`lib/type: "mbql/query"`) **is** authorable by hand thanks to the `mb query --print-schema` + `--dry-run` feedback loop; for non-trivial pipelines you may still prefer building in the UI and exporting.
220
- - Don't paste a `transform get` body into `transform update` — the PUT endpoint only accepts writable keys, and unknown keys (notably `tags`, `source_type`, `entity_id`, `created_at`, `last_run`) leak as raw SQL errors. See "Update body: send only writable keys" above. Use `tag_ids` (not `tags`) on the REST contract.
@@ -1,21 +1,21 @@
1
1
  ---
2
2
  name: visualization
3
- description: Pick the right `display` (chart type) for a card's data and author its `visualization_settings` via the `mb` CLI. Covers which chart fits which data shape, the required and optional settings per chart type, the rule that settings reference OUTPUT columns by name, minimum-viable settings per chart family, and the `column_settings` JSON-string-key footgun. The full per-chart key catalog lives in references. Load whenever choosing or shaping how a card renders — "what chart should I use for this", "create a bar chart", "make this a line chart", "turn this into a pie", "map this by state", "format this column as currency", "set the pie dimension and metric", "the card renders as a table instead of a chart", "add conditional formatting", or any `display` / `visualization_settings` work.
3
+ description: Choose a card's `display` (chart type) and author its `visualization_settings` for the `mb` CLI — which chart fits which data shape, the required keys per chart, the rule that settings name OUTPUT columns, and the `column_settings` JSON-string-key footgun; the full per-chart key catalog is in references. Use when deciding or fixing how a card renders — "what chart should I use", "make this a bar/line/pie chart", "map this by state", "format this column as currency", "add conditional formatting", "the card renders as a table instead of a chart", or any `display` / `visualization_settings` work.
4
4
  allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
5
5
  ---
6
6
 
7
7
  # Visualization: pick the chart, then set it
8
8
 
9
- > **Shared contract (read first).** This skill is part of the `robot-data-engineer` family and follows its shared rules: audience is a non-technical user, so no database jargon (skip "normalize"/"grain"; ERD/foreign key are fine; explain "wide"/"long" the first time you use them). Ask before showing PII row-by-row (names, emails, phones) — default to aggregates. When asked for something the CLI can't do (alerts, dashboard filters), name the limit instead of erroring into raw SQL. Honor the autonomy mode the user picked. Full text and the autonomy slider live in the router — run `mb skills get robot-data-engineer` and read its **Shared Contract** if you haven't.
9
+ > **Building charts as part of a guided data project?** Follow the `data-workflow` **Shared Contract** — answer-first with detail on demand, ask before showing PII, honor the autonomy mode, name what the CLI can't do instead of erroring into raw SQL: `mb skills get data-workflow`.
10
10
 
11
11
  A card has two presentation fields alongside its `dataset_query`:
12
12
 
13
- - **`display`** — the chart type (`bar`, `line`, `pie`, `scalar`, `map`, `table`, …). One closed set; pick from the enum below.
13
+ - **`display`** — the chart type (`bar`, `line`, `pie`, `scalar`, `map`, `table`, …); pick from the valid values below.
14
14
  - **`visualization_settings`** — a map whose keys are **namespaced by `display`** (`graph.*` for bar/line/area/combo, `pie.*` for pie, `table.*` for table, …). The server stores almost anything and **silently ignores keys that don't apply** to the chosen `display`.
15
15
 
16
16
  Nothing validates `visualization_settings` — there is no pre-flight to fail past. A `display` typo or a misnamed key is accepted by the API; the card just renders as a default table or drops the setting. So **the feedback loop is read-back, not pre-flight**: after `card create`/`update`, confirm with `mb card get <id> --full --json` (or open the card) that it rendered as intended.
17
17
 
18
- Flag conventions and body-input precedence live in the `core` skill (`mb skills get core`); the `dataset_query` itself is the `mbql` skill's job (`mb skills get mbql`). This skill is only about how the result is displayed.
18
+ Flag conventions and body-input precedence live in `core` (`mb skills get core`); the `dataset_query` itself is the `mbql` skill's job (`mb skills get mbql`). This skill is only about how the result is displayed.
19
19
 
20
20
  Two steps: **(1) pick the `display` that fits the data**, then **(2) bind the data columns and set options**.
21
21
 
@@ -35,7 +35,7 @@ Decide which relationship in the data matters most, then pick the chart. The sha
35
35
  - **Geographic** → `map`: region/choropleth (a region dimension + a measure), pin (lat + long), or grid/heat (coordinates + measure).
36
36
  - **Precise values, many columns, mixed types, or no chart fits** → `table`; `pivot` for a cross-tab of two dimensions; `object` for a single record's detail.
37
37
 
38
- Closed `display` enum (card-level, non-hidden): `table`, `bar`, `line`, `area`, `row`, `pie`, `scalar`, `smartscalar`, `combo`, `pivot`, `funnel`, `map`, `scatter`, `waterfall`, `progress`, `gauge`, `object`, `sankey`, `boxplot`. (`scalar` **is** the "Number" viz — `display: number` is a legacy serialization alias, not a registered visualization; use `scalar`. `list` exists but is hidden — don't pick it. `heading`/`text`/`link`/`iframe`/`action` are dashcard virtuals, not standalone cards — see references.) An unknown `display` is accepted by the API but renders nothing — typos like `bargraph`/`linechart` are the most common "why is my chart blank" cause.
38
+ Valid `display` values — the registered visualizations: `table`, `bar`, `line`, `area`, `row`, `pie`, `scalar`, `smartscalar`, `combo`, `pivot`, `funnel`, `map`, `scatter`, `waterfall`, `progress`, `gauge`, `object`, `sankey`, `boxplot`. The API types `display` as a plain string and accepts any value — it renders an unknown one as nothing. (`scalar` **is** the "Number" viz — `display: number` is a legacy serialization alias, not a registered visualization; use `scalar`. `list` exists but is hidden — don't pick it. `heading`/`text`/`link`/`iframe`/`action` are dashcard virtuals, not standalone cards — see references.) A typo like `bargraph`/`linechart` is accepted and renders blank — the most common "why is my chart blank" cause.
39
39
 
40
40
  ## Step 2 — bind data columns and set options
41
41
 
@@ -151,7 +151,7 @@ mb skills path visualization # → the skill dir; then Read references
151
151
 
152
152
  ## Don't
153
153
 
154
- - Don't invent `display` values (`bargraph`, `linechart`, `histogram`) or use `number`/`list` — use the closed non-hidden enum; the API accepts a typo and renders nothing.
154
+ - Don't invent `display` values (`bargraph`, `linechart`, `histogram`) or use `number`/`list` — use a registered value; the API accepts a typo and renders nothing.
155
155
  - Don't put numeric field ids in `graph.dimensions`/`pie.metric`/`scalar.field`/`map.latitude_column` etc. — they take **output column-name strings**.
156
156
  - Don't reach for a `pie` with >5 slices, a `combo` of unrelated metrics, or a `pie`/`scalar` to show a trend — see Step 1.
157
157
  - Don't write a `column_settings` key as an object — it's a JSON **string** (`"[\"name\",\"COL\"]"`), inner quotes escaped.
@@ -1,5 +1,17 @@
1
1
  # visualization_settings — per-chart key reference
2
2
 
3
+ ## Contents
4
+
5
+ - [Cartesian — `bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`, `boxplot`](#cartesian--bar-line-area-combo-scatter-waterfall-row-boxplot) — shared keys (binding, stacking, goal/trend, data labels, axes, tooltip) plus `scatter`, `waterfall`, `row`, `boxplot` extras
6
+ - [Part-to-whole & single value — `pie`, `funnel`, `gauge`, `progress`, `scalar`, `smartscalar`](#part-to-whole--single-value--pie-funnel-gauge-progress-scalar-smartscalar)
7
+ - [Tabular, geographic & flow — `table`, `pivot`, `object`, `map`, `sankey`](#tabular-geographic--flow--table-pivot-object-map-sankey) — includes `table.column_formatting` conditional formatting
8
+ - [`column_settings` — per-column formatting](#column_settings--per-column-formatting) — number/date/currency, `view_as`, alignment, mini bars
9
+ - [`series_settings` — per-series styling (cartesian)](#series_settings--per-series-styling-cartesian)
10
+ - [Virtual cards (dashcards only, `card_id: null`)](#virtual-cards-dashcards-only-card_id-null) — heading/text/link/iframe
11
+ - [Click behavior (dashcards only)](#click-behavior-dashcards-only)
12
+
13
+ ---
14
+
3
15
  Authorable keys per `display`, plus the data shape each chart suits and the minimum needed to render. Set keys only to override defaults — an empty `{}` works for a simple aggregate.
4
16
 
5
17
  All column-naming keys (`graph.dimensions`, `pie.dimension`, `table.columns[].name`, `map.latitude_column`, …) take **output column-name strings** — the names the query produces. Every key and value below is identical in the API form (`mb card create`) and the portable git-sync form, with two exceptions: `column_settings` `["ref", …]` keys and click-behavior dimension targets carry a numeric field id in the API form and a name-path in the portable form. In a JSON body, `column_settings` keys are escaped strings: `"[\"name\",\"TOTAL\"]"`.
@@ -20,8 +20,8 @@ mb skills get core # auth, flag conventions, every command group
20
20
  mb skills list # everything available on the installed version
21
21
  ```
22
22
 
23
- **Doing a whole job, not one command?** If the user wants an outcome — "make sense of my data", "build a data model", "go from raw data to a dashboard", "answer questions about my data", "be my data analyst", "set up analytics for X" — load the front-door router instead and let it drive:
23
+ **Doing a whole job, not one command?** If the user wants an outcome — "make sense of my data", "build a data model", "go from raw data to a dashboard", "answer questions about my data", "be my data analyst", "set up analytics for X" — load the guided end-to-end skill instead and let it drive:
24
24
 
25
25
  ```bash
26
- mb skills get robot-data-engineer
26
+ mb skills get data-workflow
27
27
  ```
@@ -1,10 +0,0 @@
1
- import "./command-augment-CAur0XOQ.mjs";
2
- import "./error-D5bZ5BUX.mjs";
3
- import "./runtime-C1QgWHM7.mjs";
4
- import "./capabilities-BX1rnVuH.mjs";
5
- import "./parse-id-DNPeV0Iu.mjs";
6
- import "./poll-CYkX02Bm.mjs";
7
- import "./poll-task-oXpl3wzp.mjs";
8
- import { SyncSettingsUpdateResult, add_collection_default, setCollectionRemoteSynced, syncSettingsUpdateView } from "./add-collection-CXhrMjXU.mjs";
9
-
10
- export { add_collection_default as default };
@@ -1,19 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/auth/index.ts
4
- var auth_default = defineCommand({
5
- meta: {
6
- name: "auth",
7
- description: "Authenticate against a Metabase instance"
8
- },
9
- default: "login",
10
- subCommands: {
11
- login: () => import("./login-Cn2UtFUt.mjs").then((m) => m.default),
12
- status: () => import("./status-Cf8c0NON.mjs").then((m) => m.default),
13
- list: () => import("./list-C6U3Ftg8.mjs").then((m) => m.default),
14
- logout: () => import("./logout-_HXgEmqA.mjs").then((m) => m.default)
15
- }
16
- });
17
-
18
- //#endregion
19
- export { auth_default as default };
@@ -1,20 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/card/index.ts
4
- var card_default = defineCommand({
5
- meta: {
6
- name: "card",
7
- description: "Manage Metabase cards (questions, models, metrics)"
8
- },
9
- subCommands: {
10
- list: () => import("./list-C410Ptw_.mjs").then((mod) => mod.default),
11
- get: () => import("./get-Wj88mnhn.mjs").then((mod) => mod.default),
12
- query: () => import("./query-DWQaN7hO.mjs").then((mod) => mod.default),
13
- create: () => import("./create-4mAGsBd0.mjs").then((mod) => mod.default),
14
- update: () => import("./update-rhfPHALN.mjs").then((mod) => mod.default),
15
- archive: () => import("./archive-BUwiCFnd.mjs").then((mod) => mod.default)
16
- }
17
- });
18
-
19
- //#endregion
20
- export { card_default as default };
@@ -1,20 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/collection/index.ts
4
- var collection_default = defineCommand({
5
- meta: {
6
- name: "collection",
7
- description: "Manage Metabase collections"
8
- },
9
- subCommands: {
10
- list: () => import("./list-CfWblVHJ.mjs").then((mod) => mod.default),
11
- get: () => import("./get-DAsaor0n.mjs").then((mod) => mod.default),
12
- items: () => import("./items-LjtICjvX.mjs").then((mod) => mod.default),
13
- tree: () => import("./tree-CF8mscd9.mjs").then((mod) => mod.default),
14
- create: () => import("./create-C7FPeJqF.mjs").then((mod) => mod.default),
15
- archive: () => import("./archive-CQiaCBSj.mjs").then((mod) => mod.default)
16
- }
17
- });
18
-
19
- //#endregion
20
- export { collection_default as default };
@@ -1,21 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/dashboard/index.ts
4
- var dashboard_default = defineCommand({
5
- meta: {
6
- name: "dashboard",
7
- description: "Manage Metabase dashboards"
8
- },
9
- subCommands: {
10
- list: () => import("./list-ChK06rJh.mjs").then((mod) => mod.default),
11
- get: () => import("./get-qnGGGRTa.mjs").then((mod) => mod.default),
12
- cards: () => import("./cards-BySIFsLG.mjs").then((mod) => mod.default),
13
- create: () => import("./create-C43RQYgj.mjs").then((mod) => mod.default),
14
- update: () => import("./update-DERsb0eO.mjs").then((mod) => mod.default),
15
- "update-dashcard": () => import("./update-dashcard-BJVeSGvO.mjs").then((mod) => mod.default),
16
- archive: () => import("./archive-BxGSR7El.mjs").then((mod) => mod.default)
17
- }
18
- });
19
-
20
- //#endregion
21
- export { dashboard_default as default };
@@ -1,22 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/db/index.ts
4
- var db_default = defineCommand({
5
- meta: {
6
- name: "db",
7
- description: "Inspect and sync Metabase databases",
8
- alias: "database"
9
- },
10
- subCommands: {
11
- list: () => import("./list-Dq86BAMG.mjs").then((m) => m.default),
12
- get: () => import("./get-CGkhSY5L.mjs").then((m) => m.default),
13
- metadata: () => import("./metadata-8yqT8OZI.mjs").then((m) => m.default),
14
- schemas: () => import("./schemas-Cr7RjYqV.mjs").then((m) => m.default),
15
- "schema-tables": () => import("./schema-tables-rdeupgsu.mjs").then((m) => m.default),
16
- "sync-schema": () => import("./sync-schema-DKEel2Sv.mjs").then((m) => m.default),
17
- "rescan-values": () => import("./rescan-values-B9Qtsd32.mjs").then((m) => m.default)
18
- }
19
- });
20
-
21
- //#endregion
22
- export { db_default as default };
@@ -1,19 +0,0 @@
1
- import { defineCommand } from "citty";
2
-
3
- //#region src/commands/document/index.ts
4
- var document_default = defineCommand({
5
- meta: {
6
- name: "document",
7
- description: "Manage Metabase documents"
8
- },
9
- subCommands: {
10
- list: () => import("./list-Bjp9nd0o.mjs").then((mod) => mod.default),
11
- get: () => import("./get-BtAD26gc.mjs").then((mod) => mod.default),
12
- create: () => import("./create-DnT1Sayk.mjs").then((mod) => mod.default),
13
- update: () => import("./update-CgQOSuZt.mjs").then((mod) => mod.default),
14
- archive: () => import("./archive-yTvDRQUZ.mjs").then((mod) => mod.default)
15
- }
16
- });
17
-
18
- //#endregion
19
- export { document_default as default };