@metabase/cli 0.1.5 → 0.1.7
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/README.md +128 -115
- package/dist/add-collection-C9BdVBs2.mjs +11 -0
- package/dist/{add-collection-C_iovi9i.mjs → add-collection-DQjTlDNF.mjs} +12 -5
- package/dist/archive-B3qiL-kK.mjs +40 -0
- package/dist/{archive-DdaP94H3.mjs → archive-BXzghEQX.mjs} +10 -9
- package/dist/{archive-WaEW85NB.mjs → archive-CBGKzEAl.mjs} +9 -8
- package/dist/{archive-BKPO8lEO.mjs → archive-CuVk8iwN.mjs} +10 -9
- package/dist/archive-DTN9tLGT.mjs +40 -0
- package/dist/{archive-Dvzrmdbk.mjs → archive-De8jzzq7.mjs} +10 -9
- package/dist/auth-D9eAyVoG.mjs +19 -0
- package/dist/{body-XtR7-uCO.mjs → body-tcURGnGh.mjs} +4 -4
- package/dist/{branches-XUY4JY-X.mjs → branches-CIGkjXIk.mjs} +11 -7
- package/dist/{cancel-BrUVO_ax.mjs → cancel-pPsvgJ0Z.mjs} +9 -8
- package/dist/{cancel-task-oXheTOB6.mjs → cancel-task-BLGE4UlL.mjs} +12 -8
- package/dist/capabilities-7e9MgquN.mjs +29 -0
- package/dist/card-DDDrWcDU.mjs +20 -0
- package/dist/{card-CQxvHeyP.mjs → card-ezYiriML.mjs} +1 -1
- package/dist/{cards-CONTTAG9.mjs → cards-Dq3nx_9n.mjs} +8 -7
- package/dist/cli.mjs +264 -44
- package/dist/collection-DkEvCDar.mjs +20 -0
- package/dist/{predicates-CGO17Q15.mjs → command-augment-BH9qgQ5u.mjs} +66 -14
- package/dist/{create-Cs2xntFG.mjs → create-9DBTkbMq.mjs} +18 -16
- package/dist/{create-kYpjobrq.mjs → create-B1dyuL9Y.mjs} +16 -10
- package/dist/create-BIphz0kO.mjs +52 -0
- package/dist/create-BcgoukG4.mjs +50 -0
- package/dist/create-BdPoSk_7.mjs +50 -0
- package/dist/{create-DZxUeqdf.mjs → create-BrUqxreg.mjs} +11 -10
- package/dist/create-DHscDhRd.mjs +50 -0
- package/dist/{create-Dq25vsMu.mjs → create-aPaUEGdr.mjs} +11 -10
- package/dist/{create-branch-D5u14AxL.mjs → create-branch-DGoc9CUU.mjs} +12 -8
- package/dist/{create-Ca9lIDwP.mjs → create-w3mQg9n4.mjs} +11 -10
- package/dist/{credentials-BIQ1cEzM.mjs → credentials-qryRLUed.mjs} +12 -11
- package/dist/current-task-DZM28rnr.mjs +40 -0
- package/dist/{dashboard-CnMD04PQ.mjs → dashboard-B4bn3z6t.mjs} +2 -1
- package/dist/dashboard-BLf1RZlk.mjs +21 -0
- package/dist/{database-vvig8k4x.mjs → database-BXiue1in.mjs} +1 -1
- package/dist/{database-BSvzYlRe.mjs → database-Ce1gOJF7.mjs} +3 -3
- package/dist/db-CWTFe_FZ.mjs +22 -0
- package/dist/{delete-VTAS9EUt.mjs → delete-BPaFdHZP.mjs} +11 -8
- package/dist/{delete-CUx6RT9e.mjs → delete-BrJOotpW.mjs} +11 -8
- package/dist/{remove-C6bS0Z6w.mjs → delete-FFj1xQWO.mjs} +25 -20
- package/dist/{delete-runtime-DfFMWJJ6.mjs → delete-runtime-uuYbd4k2.mjs} +9 -7
- package/dist/{delete-table-DzUneMKe.mjs → delete-table-CNupWUO0.mjs} +11 -8
- package/dist/{deprovision-CpJfGgCt.mjs → deprovision-BNr9fPDY.mjs} +18 -12
- package/dist/{dirty-nkAOXxgC.mjs → dirty-BCkNOY8c.mjs} +11 -7
- package/dist/{docker-D5FTIoD0.mjs → docker-Ds252Mwc.mjs} +4 -4
- package/dist/{translate-Cqsd0Px5.mjs → eid-CLY5X0Uw.mjs} +43 -23
- package/dist/error-ZsFeevV2.mjs +191 -0
- package/dist/{export-BWvY7X_G.mjs → export-CgHgWW3I.mjs} +20 -18
- package/dist/{field-B3gvaqpK.mjs → field-E0IBy4Uw.mjs} +12 -3
- package/dist/field-LL6W_c-c.mjs +18 -0
- package/dist/{fields-dH16G5UV.mjs → fields-RkRWU-u9.mjs} +9 -8
- package/dist/{get-D96QEU49.mjs → get-42tJ7BNp.mjs} +8 -7
- package/dist/{get-C6SR3A9t.mjs → get-B8l4t4Pz.mjs} +10 -9
- package/dist/{get-BnBRKHr7.mjs → get-B9kwSs6U.mjs} +8 -7
- package/dist/{get-7macOPAI.mjs → get-Bo4Cpd_c.mjs} +7 -7
- package/dist/{get-BcqxMVC1.mjs → get-C9O_aEGo.mjs} +8 -7
- package/dist/{get-CKxlhMy1.mjs → get-CRvbChoX.mjs} +8 -7
- package/dist/{get-B7i_nYJB.mjs → get-CTDqioaj.mjs} +8 -7
- package/dist/{get-D8e_RzZ0.mjs → get-CiZrZJLt.mjs} +10 -9
- package/dist/{get-B08K82JV.mjs → get-CvmqPN30.mjs} +8 -7
- package/dist/{get-CACaBFLt.mjs → get-DmzgSgrl.mjs} +9 -8
- package/dist/{get-R7OaVL_t.mjs → get-DsqGHNHN.mjs} +8 -7
- package/dist/get-run-CBwcRc8E.mjs +38 -0
- package/dist/{get-DNN1X2gN.mjs → get-sMpa-X4E.mjs} +9 -8
- package/dist/{get-DAWofnzK.mjs → get-y17zJMnU.mjs} +8 -7
- package/dist/git-sync-CrWTo3YX.mjs +28 -0
- package/dist/{has-remote-changes-BAnIXQXU.mjs → has-remote-changes-CfRidwXT.mjs} +13 -8
- package/dist/{import-CfdPEMng.mjs → import-BZV0Z2KR.mjs} +21 -18
- package/dist/{input-BQ-BZA8h.mjs → input-cMSEqISy.mjs} +7 -4
- package/dist/is-dirty-CPzOnnH6.mjs +10 -0
- package/dist/{is-dirty-CZWcG0vj.mjs → is-dirty-hKcB4OH9.mjs} +9 -4
- package/dist/{items-DqwahOKf.mjs → items-C94eW2Yd.mjs} +10 -9
- package/dist/key-vkNkH82H.mjs +17 -0
- package/dist/license-B37055sr.mjs +17 -0
- package/dist/{list-L63TpX1t.mjs → list-B0V7FeL2.mjs} +7 -7
- package/dist/{list-Bkd7Nbds.mjs → list-BFlzLGlw.mjs} +7 -6
- package/dist/{list-yxVAE1S7.mjs → list-BJXaGk-z.mjs} +7 -6
- package/dist/{list-BqNMpIXy.mjs → list-BS_Bxejg.mjs} +9 -8
- package/dist/{list-J277Qtki.mjs → list-BmHoYJr7.mjs} +7 -6
- package/dist/list-C-oZe1_p.mjs +173 -0
- package/dist/{list-ViT2KWhv.mjs → list-CF1pMN4S.mjs} +7 -6
- package/dist/{list-BpNU1neq.mjs → list-CU6sOfI-.mjs} +9 -7
- package/dist/{list-oftHLFbE.mjs → list-CqN4gvCk.mjs} +9 -7
- package/dist/{list-DBOYoJtA.mjs → list-DUXdt0XI.mjs} +10 -6
- package/dist/{list-D41gfkKb.mjs → list-DfDZr55C.mjs} +10 -8
- package/dist/{list-vF4EneaE.mjs → list-DrINpVLM.mjs} +7 -6
- package/dist/{list-DJcGwJ4W.mjs → list-DuSoEk_J.mjs} +9 -8
- package/dist/{list-CQkDqphl.mjs → list-HS15y_WN.mjs} +7 -6
- package/dist/login-enh9Yimb.mjs +181 -0
- package/dist/{logout-DD4q5whi.mjs → logout-BWLPLDh8.mjs} +13 -11
- package/dist/{logs-Ci3mJE2z.mjs → logs-Cu3QtvPs.mjs} +9 -8
- package/dist/{manifest-CGM7XNLC.mjs → manifest-BNh0Lw6p.mjs} +15 -15
- package/dist/{measure-BEQfnLdN.mjs → measure-Bt3InQsA.mjs} +2 -2
- package/dist/measure-CDlEPFtB.mjs +19 -0
- package/dist/{metadata-BDat-jN9.mjs → metadata-BTTEBWdS.mjs} +10 -9
- package/dist/{metadata-29_qlqbz.mjs → metadata-D2TxboMm.mjs} +9 -8
- package/dist/parse-enum-CrEWOhuY.mjs +11 -0
- package/dist/{parse-id-CysSaCbf.mjs → parse-id-0_tOPvfI.mjs} +1 -1
- package/dist/{parse-ref-D1yeDOn8.mjs → parse-ref-DKag6a6I.mjs} +1 -1
- package/dist/{parse-schemas-B10n01ez.mjs → parse-schemas-D-qVLl4z.mjs} +2 -2
- package/dist/{path-DLByFMMA.mjs → path-C8GrBdgT.mjs} +7 -7
- package/dist/{poll-p9Y7-JEQ.mjs → poll-4eoh5J0r.mjs} +2 -2
- package/dist/{poll-task-BQe0NvJZ.mjs → poll-task-51WRdugU.mjs} +19 -20
- package/dist/{preflight-CvFu0Cct.mjs → preflight-BhsErYz3.mjs} +4 -4
- package/dist/{process-zJeVJZTM.mjs → process-CM7Uu5q_.mjs} +1 -1
- package/dist/{prompt-DgDNy_Pc.mjs → prompt-CFKoys7k.mjs} +3 -1
- package/dist/provision-Chf86BF0.mjs +83 -0
- package/dist/{ps-BxQdpkr5.mjs → ps-CEYtsKBj.mjs} +5 -3
- package/dist/ps-CIDwaubS.mjs +11 -0
- package/dist/{query-C7zTlFJA.mjs → query-BBCAF-tG.mjs} +17 -14
- package/dist/{query-CFH4nBlK.mjs → query-DYVBnu9d.mjs} +12 -9
- package/dist/query-result-ABPLz6I4.mjs +19 -0
- package/dist/{remove-BuWxx3hY.mjs → remove-2yInufA6.mjs} +14 -12
- package/dist/remove-collection-CBAHz0Dk.mjs +44 -0
- package/dist/{render-DuoDUTVL.mjs → render-0_GsapXa.mjs} +51 -23
- package/dist/render-khznBlla.mjs +32 -0
- package/dist/{rescan-values-DabyRYQ_.mjs → rescan-values-cfTSNQZo.mjs} +12 -11
- package/dist/{run-Cl-9RtC4.mjs → run-qgdEJv-I.mjs} +17 -15
- package/dist/{runs-BH6s1Zao.mjs → runs-BFIIH4GL.mjs} +9 -8
- package/dist/{runtime-CDu6fykq.mjs → runtime-Duawf5lE.mjs} +653 -428
- package/dist/{schema-tables-i58wp_p3.mjs → schema-tables-C2xM3dho.mjs} +9 -8
- package/dist/{schemas-_m8RYRl9.mjs → schemas-BP7xiktH.mjs} +7 -6
- package/dist/{search-DObOsjbP.mjs → search-DYP3lOlq.mjs} +12 -16
- package/dist/segment-B6HnNGDs.mjs +19 -0
- package/dist/{set-CwVWeAsi.mjs → set-DpRQqdo7.mjs} +13 -11
- package/dist/{set-CJA9dpK6.mjs → set-Tt-ioa4L.mjs} +14 -13
- package/dist/setting-DUa96KF3.mjs +17 -0
- package/dist/{setup-DqBOe3HZ.mjs → setup-BPlllnim.mjs} +10 -9
- package/dist/{skills-CHU7uuDU.mjs → skills-BkregMyb.mjs} +2 -2
- package/dist/{skills-C2rTVj0n.mjs → skills-SqbPo0BI.mjs} +3 -3
- package/dist/snippet-dJ68tGsl.mjs +19 -0
- package/dist/{start-CfruN4wF.mjs → start-DJZA67WF.mjs} +70 -38
- package/dist/{stash-CWuXKSZq.mjs → stash-C89zNKxo.mjs} +21 -18
- package/dist/{status-D-RYZB9G.mjs → status-B1EJ_jv0.mjs} +16 -9
- package/dist/status-BNvFPemM.mjs +100 -0
- package/dist/status-D5wSqYV_.mjs +34 -0
- package/dist/{stop-D8Hr4cKX.mjs → stop-5rCLmkCQ.mjs} +16 -11
- package/dist/{summary-Lt2XLBK9.mjs → summary-Cihbx0Qs.mjs} +8 -7
- package/dist/{sync-schema-BDElSynU.mjs → sync-schema-C3odu0ZH.mjs} +12 -11
- package/dist/table-J2f0STnB.mjs +19 -0
- package/dist/{table-B-PYcgGb.mjs → table-qDD2kApF.mjs} +1 -1
- package/dist/{transform-job-BrhOLO4M.mjs → transform-job-DjhoJbiV.mjs} +1 -1
- package/dist/transform-job-OW4SDhsQ.mjs +19 -0
- package/dist/transform-q1LYWQtW.mjs +24 -0
- package/dist/{tree-DfvjDjmk.mjs → tree-mvq9gM9w.mjs} +7 -6
- package/dist/{update-DzgXF082.mjs → update-BoIiuC70.mjs} +16 -14
- package/dist/{update-qnFY5IuC.mjs → update-C0jP0AKT.mjs} +12 -11
- package/dist/{update-zp7pCBZH.mjs → update-CbBnHz42.mjs} +16 -14
- package/dist/{update-B0bjPqKC.mjs → update-CtOo3LsX.mjs} +13 -12
- package/dist/{update-CVxOxmt6.mjs → update-DCrOQ1PW.mjs} +17 -15
- package/dist/{update-BYduslhn.mjs → update-DEZayTb4.mjs} +20 -15
- package/dist/{update-BgcroYkF.mjs → update-DwRxdflw.mjs} +12 -11
- package/dist/{update-D9Z8cL7h.mjs → update-Rr4usmCo.mjs} +12 -11
- package/dist/{update-DuA8-cCq.mjs → update-VvKMnwsM.mjs} +16 -14
- package/dist/{update-dashcard-CQ3kmmss.mjs → update-dashcard-DFvIz8Qj.mjs} +12 -11
- package/dist/{update-CqnDMNtZ.mjs → update-tRparnUs.mjs} +18 -16
- package/dist/{upgrade-CIgTr2CG.mjs → upgrade-D-Rl_fH9.mjs} +16 -29
- package/dist/{url-B5MgZXzg.mjs → url-BB6jeNQj.mjs} +11 -10
- package/dist/{uuid-CJz9TmHI.mjs → uuid-BSVUk8u2.mjs} +8 -6
- package/dist/{validate-CB0bu50i.mjs → validate-dPEOnOf8.mjs} +2 -1
- package/dist/{validate-query-CavIA0Q2.mjs → validate-query-CYvOP8Ld.mjs} +3 -3
- package/dist/values-D1RJE4H6.mjs +45 -0
- package/dist/verify-A7BWfBPZ.mjs +79 -0
- package/dist/{wait-BFqBlg0y.mjs → wait-B17I_pWy.mjs} +2 -2
- package/dist/{wait-tDp9ZOou.mjs → wait-DK5QDZ8n.mjs} +14 -10
- package/dist/{wait-flags-CN-e9zNq.mjs → wait-flags-DlfbIXHw.mjs} +20 -9
- package/dist/{workspace-credentials-4lIxxz4g.mjs → workspace-credentials-8CBMQJFz.mjs} +2 -2
- package/dist/workspace-ri6r3zWo.mjs +25 -0
- package/dist/{yaml-ECiog374.mjs → yaml-Gv6wRFMF.mjs} +1 -1
- package/package.json +2 -1
- package/skill-data/core/SKILL.md +55 -453
- package/skill-data/git-sync/SKILL.md +1 -1
- package/skill-data/mbql/SKILL.md +156 -0
- package/skill-data/mbql/references/operators.md +253 -0
- package/skill-data/transform/SKILL.md +2 -40
- package/skill-data/viz/SKILL.md +137 -0
- package/skill-data/viz/references/settings.md +312 -0
- package/skill-data/workspace/SKILL.md +45 -63
- package/skills/metabase-cli/SKILL.md +5 -26
- package/dist/add-collection-ucsyAMkV.mjs +0 -11
- package/dist/api-key-BENHbTbV.mjs +0 -13
- package/dist/auth-DICRtJDy.mjs +0 -19
- package/dist/card-l-UmrUIo.mjs +0 -20
- package/dist/collection-oV0olVY-.mjs +0 -19
- package/dist/command-augment-D9pI9Vbh.mjs +0 -11
- package/dist/create-CrUq6sib.mjs +0 -125
- package/dist/create-D3Z878yr.mjs +0 -50
- package/dist/create-Le3Bqn7b.mjs +0 -48
- package/dist/create-V-q2rU0T.mjs +0 -48
- package/dist/create-swbIXdo5.mjs +0 -48
- package/dist/current-task-DCq7rk9V.mjs +0 -36
- package/dist/dashboard-hbKDd36X.mjs +0 -20
- package/dist/db-qVK6NsdB.mjs +0 -22
- package/dist/eid-CDFXX_6H.mjs +0 -13
- package/dist/field-C0LE7RQI.mjs +0 -18
- package/dist/flag-pair-Fmcdkrfx.mjs +0 -17
- package/dist/get-run-CwFuR4Uw.mjs +0 -36
- package/dist/git-sync-DV7YjniX.mjs +0 -28
- package/dist/is-dirty-LxVbm2C5.mjs +0 -10
- package/dist/key-CCJdVWKc.mjs +0 -12
- package/dist/license-Cb6ewEJO.mjs +0 -17
- package/dist/list-DV6CONhp.mjs +0 -55
- package/dist/login-D1nZwgKv.mjs +0 -192
- package/dist/measure-XhJuL77y.mjs +0 -19
- package/dist/package-DFUprkSZ.mjs +0 -85
- package/dist/provision-BP-b4Are.mjs +0 -77
- package/dist/ps-Bk6unzaX.mjs +0 -11
- package/dist/remove-collection-Bc4roCq0.mjs +0 -38
- package/dist/segment-DfxZdJmR.mjs +0 -19
- package/dist/setting-Czy4ws6h.mjs +0 -18
- package/dist/snippet-BCY4KHBU.mjs +0 -19
- package/dist/status-1oUnw803.mjs +0 -56
- package/dist/status-J9HIDcA5.mjs +0 -32
- package/dist/table-BwX3Ib5f.mjs +0 -19
- package/dist/transform-iaAi37V0.mjs +0 -24
- package/dist/transform-job-Bemonf82.mjs +0 -19
- package/dist/values-BXN6tx1i.mjs +0 -36
- package/dist/workspace-BBsT0H0g.mjs +0 -24
- /package/dist/{body-flags-BK7J6Daz.mjs → body-flags-D7q87Btw.mjs} +0 -0
- /package/dist/{collection-B3sPXRLs.mjs → collection-Bcy8cWYH.mjs} +0 -0
- /package/dist/{paginate-CTSfuYiF.mjs → paginate-BexjkjbY.mjs} +0 -0
- /package/dist/{revision-message-flag-oyq2xrDU.mjs → revision-message-flag-DY29-cgz.mjs} +0 -0
- /package/dist/{segment-BMrUBz94.mjs → segment-DhBmcr_E.mjs} +0 -0
- /package/dist/{setting-CTaAeMci.mjs → setting-BzCng1Ub.mjs} +0 -0
- /package/dist/{snippet-CSWqkslB.mjs → snippet-bi_0XbNT.mjs} +0 -0
- /package/dist/{transform-DR4ejuPM.mjs → transform-BKahefz_.mjs} +0 -0
- /package/dist/{workspace-DUfqhPm5.mjs → workspace-D8HtUN0y.mjs} +0 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# visualization_settings — full key catalog
|
|
2
|
+
|
|
3
|
+
Exhaustive reference for `visualization_settings`. The SKILL.md body covers the
|
|
4
|
+
common cases; this file is the long tail. Keys are grouped by the `display` they
|
|
5
|
+
apply to (see the display → namespace map in the body).
|
|
6
|
+
|
|
7
|
+
**Form note.** Every key name and value enum below is identical in the API/numeric
|
|
8
|
+
form (`mb card create`) and the portable git-sync YAML form. The only form-specific
|
|
9
|
+
constructs are (1) `column_settings` `["ref", …]` keys, where the inner field id is
|
|
10
|
+
numeric in the API form and a name-path in the portable form, and (2) click-behavior
|
|
11
|
+
dimension targets, same rule. All the column-naming keys (`graph.dimensions`,
|
|
12
|
+
`pie.dimension`, `table.columns[].name`, …) are output column-name strings in both.
|
|
13
|
+
|
|
14
|
+
JSON-body reminder: examples here are shown as YAML/JSON fragments. In a real
|
|
15
|
+
`--body`/`--file` JSON payload, `column_settings` keys are JSON **strings** with
|
|
16
|
+
escaped inner quotes: `"[\"name\",\"TOTAL\"]"`.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Common
|
|
21
|
+
|
|
22
|
+
| Setting | Type | Description |
|
|
23
|
+
| --------------------- | ------- | ------------------------------------------------------------------- |
|
|
24
|
+
| `column_settings` | map | Per-column formatting, keyed by column-reference string (see below) |
|
|
25
|
+
| `card.title` | string | Override the card's display title on a dashboard |
|
|
26
|
+
| `card.description` | string | Override the description |
|
|
27
|
+
| `dashcard.background` | boolean | Show/hide the dashcard background (dashcards only) |
|
|
28
|
+
|
|
29
|
+
## Graph (`bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`, `boxplot`)
|
|
30
|
+
|
|
31
|
+
| Setting | Type | Values / notes |
|
|
32
|
+
| --------------------------------------- | -------------- | ------------------------------------------------------------------------ |
|
|
33
|
+
| `graph.dimensions` | array | Dimension (x-axis) output column names |
|
|
34
|
+
| `graph.metrics` | array | Metric (y-axis) output column names |
|
|
35
|
+
| `graph.series_order` | array | Explicit series display order |
|
|
36
|
+
| `graph.show_values` | boolean | Show value labels on data points |
|
|
37
|
+
| `graph.label_values_frequency` | string | `"fit"`, `"all"` |
|
|
38
|
+
| `graph.show_stack_values` | string | `"total"`, `"individual"`, `"all"` |
|
|
39
|
+
| `graph.x_axis.title_text` | string | X-axis title |
|
|
40
|
+
| `graph.x_axis.scale` | string | `"ordinal"`, `"histogram"`, `"timeseries"`, `"linear"`, `"pow"`, `"log"` |
|
|
41
|
+
| `graph.x_axis.axis_enabled` | boolean/string | `true`, `false`, `"compact"`, `"rotate-45"`, `"rotate-90"` |
|
|
42
|
+
| `graph.y_axis.title_text` | string | Y-axis title |
|
|
43
|
+
| `graph.y_axis.scale` | string | `"linear"`, `"pow"`, `"log"` |
|
|
44
|
+
| `graph.y_axis.auto_range` | boolean | Auto-scale Y axis |
|
|
45
|
+
| `graph.y_axis.min` / `graph.y_axis.max` | number | Y bounds when `auto_range` is false |
|
|
46
|
+
| `graph.show_goal` | boolean | Show goal line |
|
|
47
|
+
| `graph.goal_value` | number | Goal line value |
|
|
48
|
+
| `graph.goal_label` | string | Goal line label |
|
|
49
|
+
| `graph.show_trendline` | boolean | Show trend line |
|
|
50
|
+
| `graph.max_categories_enabled` | boolean | Limit number of categories |
|
|
51
|
+
| `graph.max_categories` | number | Maximum categories shown |
|
|
52
|
+
| `graph.other_category_aggregation_fn` | string | `"sum"`, `"avg"`, `"min"`, `"max"` |
|
|
53
|
+
| `stackable.stack_type` | string | `null`, `"stacked"`, `"normalized"` |
|
|
54
|
+
|
|
55
|
+
### Series settings
|
|
56
|
+
|
|
57
|
+
Per-series overrides keyed by series name (the metric column name, or the breakout
|
|
58
|
+
value for a split series):
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
series_settings:
|
|
62
|
+
Revenue:
|
|
63
|
+
display: line # override this series' type in a combo chart
|
|
64
|
+
color: "#509EE3"
|
|
65
|
+
"line.style": solid # "solid", "dashed", "dotted"
|
|
66
|
+
"line.size": normal # "S", "M", "L"
|
|
67
|
+
"line.interpolate": linear # "linear", "cardinal", "step-before", "step-after"
|
|
68
|
+
"line.missing": interpolate # "interpolate", "zero", "none"
|
|
69
|
+
"line.marker_enabled": true
|
|
70
|
+
axis: left # "left", "right"
|
|
71
|
+
show_series_values: true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Waterfall extras (`display: waterfall`)
|
|
75
|
+
|
|
76
|
+
| Setting | Type | Description |
|
|
77
|
+
| -------------------------- | ------- | ----------------------- |
|
|
78
|
+
| `waterfall.increase_color` | string | Color for increases |
|
|
79
|
+
| `waterfall.decrease_color` | string | Color for decreases |
|
|
80
|
+
| `waterfall.total_color` | string | Color for the total bar |
|
|
81
|
+
| `waterfall.show_total` | boolean | Show the total bar |
|
|
82
|
+
|
|
83
|
+
### BoxPlot extras (`display: boxplot`)
|
|
84
|
+
|
|
85
|
+
| Setting | Type | Values |
|
|
86
|
+
| ---------------------- | ------- | -------------------------------------- |
|
|
87
|
+
| `boxplot.whisker_type` | string | `"min-max"`, `"tukey"`, `"percentile"` |
|
|
88
|
+
| `boxplot.points_mode` | string | `"none"`, `"outliers"`, `"all"` |
|
|
89
|
+
| `boxplot.show_mean` | boolean | Show mean marker |
|
|
90
|
+
|
|
91
|
+
## Pie (`display: pie`)
|
|
92
|
+
|
|
93
|
+
| Setting | Type | Values |
|
|
94
|
+
| ------------------------ | ------- | ----------------------------------------- |
|
|
95
|
+
| `pie.dimension` | string | Dimension column name |
|
|
96
|
+
| `pie.metric` | string | Metric column name |
|
|
97
|
+
| `pie.show_legend` | boolean | |
|
|
98
|
+
| `pie.show_total` | boolean | Show total in center |
|
|
99
|
+
| `pie.percent_visibility` | string | `"off"`, `"legend"`, `"inside"`, `"both"` |
|
|
100
|
+
| `pie.slice_threshold` | number | Min percentage to show as its own slice |
|
|
101
|
+
| `pie.colors` | object | Color map keyed by dimension value |
|
|
102
|
+
|
|
103
|
+
## Scalar / Number (`display: scalar`, `number`)
|
|
104
|
+
|
|
105
|
+
| Setting | Type | Values |
|
|
106
|
+
| --------------------------------- | ------- | ------------------------------- |
|
|
107
|
+
| `scalar.field` | string | Output column to display |
|
|
108
|
+
| `scalar.switch_positive_negative` | boolean | Invert positive/negative colors |
|
|
109
|
+
| `scalar.compact_primary_number` | string | `"auto"`, `"yes"`, `"no"` |
|
|
110
|
+
|
|
111
|
+
### Smart scalar (`display: smartscalar`)
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
scalar.comparisons:
|
|
115
|
+
- id: comp1
|
|
116
|
+
type: previousPeriod # vs. previous time period
|
|
117
|
+
- id: comp2
|
|
118
|
+
type: previousValue # vs. previous value
|
|
119
|
+
- id: comp3
|
|
120
|
+
type: periodsAgo # vs. N periods ago
|
|
121
|
+
value: 12
|
|
122
|
+
- id: comp4
|
|
123
|
+
type: staticNumber # vs. fixed number
|
|
124
|
+
value: 1000
|
|
125
|
+
label: Target
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Funnel (`display: funnel`)
|
|
129
|
+
|
|
130
|
+
| Setting | Type | Values |
|
|
131
|
+
| ------------------ | ------ | --------------------- |
|
|
132
|
+
| `funnel.dimension` | string | Dimension column |
|
|
133
|
+
| `funnel.metric` | string | Metric column |
|
|
134
|
+
| `funnel.type` | string | `"funnel"` or `"bar"` |
|
|
135
|
+
| `funnel.rows` | array | Row order definitions |
|
|
136
|
+
|
|
137
|
+
## Gauge (`display: gauge`)
|
|
138
|
+
|
|
139
|
+
| Setting | Type | Description |
|
|
140
|
+
| ---------------------- | ----- | ------------------------------------------- |
|
|
141
|
+
| `gauge.segments` | array | Segments, each `{ min, max, color, label }` |
|
|
142
|
+
| `gauge.segment_colors` | array | Segment colors |
|
|
143
|
+
|
|
144
|
+
## Map (`display: map`)
|
|
145
|
+
|
|
146
|
+
| Setting | Type | Values |
|
|
147
|
+
| ---------------------------------------------- | ------ | -------------------------------- |
|
|
148
|
+
| `map.type` | string | `"region"`, `"pin"`, `"grid"` |
|
|
149
|
+
| `map.latitude_column` | string | Latitude column name |
|
|
150
|
+
| `map.longitude_column` | string | Longitude column name |
|
|
151
|
+
| `map.metric_column` | string | Metric column for coloring |
|
|
152
|
+
| `map.region` | string | Region map identifier |
|
|
153
|
+
| `map.pin_type` | string | `"tiles"`, `"markers"`, `"heat"` |
|
|
154
|
+
| `map.colors` | array | Color scale |
|
|
155
|
+
| `map.zoom` | number | Initial zoom level |
|
|
156
|
+
| `map.center_latitude` / `map.center_longitude` | number | Map center |
|
|
157
|
+
|
|
158
|
+
## Table (`display: table`)
|
|
159
|
+
|
|
160
|
+
| Setting | Type | Description |
|
|
161
|
+
| ------------------------- | ------- | --------------------------------------------------------- |
|
|
162
|
+
| `table.columns` | array | Column order + visibility; each entry `{ name, enabled }` |
|
|
163
|
+
| `table.column_formatting` | array | Conditional formatting rules (see below) |
|
|
164
|
+
| `table.pivot` | boolean | Enable in-table pivot mode |
|
|
165
|
+
| `table.pivot_column` | string | Column to pivot on |
|
|
166
|
+
| `table.cell_column` | string | Column used for cell values (pivot mode) |
|
|
167
|
+
|
|
168
|
+
### Conditional formatting (`table.column_formatting`)
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
table.column_formatting:
|
|
172
|
+
- columns: [Total]
|
|
173
|
+
type: single # "single" or "range"
|
|
174
|
+
operator: ">" # "=", "!=", "<", ">", "<=", ">=", "is-null", "not-null"
|
|
175
|
+
value: 100
|
|
176
|
+
color: "#84BB4C"
|
|
177
|
+
highlight_row: false
|
|
178
|
+
- columns: [Rating]
|
|
179
|
+
type: range
|
|
180
|
+
colors: ["#ED6E6E", "#F9CF48", "#84BB4C"]
|
|
181
|
+
min_type: custom # "min", "max", "custom"
|
|
182
|
+
min_value: 1
|
|
183
|
+
max_type: custom
|
|
184
|
+
max_value: 5
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Pivot table (`display: pivot`)
|
|
188
|
+
|
|
189
|
+
| Setting | Type | Description |
|
|
190
|
+
| -------------------------------- | ------- | --------------------------------------------------------------- |
|
|
191
|
+
| `pivot_table.column_split` | object | `{ rows: [...names], columns: [...names], values: [...names] }` |
|
|
192
|
+
| `pivot_table.collapsed_rows` | object | `{ rows: [...collapsed_keys], value: [] }` |
|
|
193
|
+
| `pivot_table.show_row_totals` | boolean | |
|
|
194
|
+
| `pivot_table.show_column_totals` | boolean | |
|
|
195
|
+
|
|
196
|
+
## Sankey (`display: sankey`)
|
|
197
|
+
|
|
198
|
+
| Setting | Type | Values |
|
|
199
|
+
| ------------------------- | ------- | -------------------------------------------- |
|
|
200
|
+
| `sankey.source` | string | Source column |
|
|
201
|
+
| `sankey.target` | string | Target column |
|
|
202
|
+
| `sankey.value` | string | Value column |
|
|
203
|
+
| `sankey.node_align` | string | `"left"`, `"right"`, `"center"`, `"justify"` |
|
|
204
|
+
| `sankey.show_edge_labels` | boolean | |
|
|
205
|
+
|
|
206
|
+
## Column settings
|
|
207
|
+
|
|
208
|
+
`column_settings` is keyed by a JSON-encoded column reference. Prefer the
|
|
209
|
+
`["name", "<output column name>"]` form — it is the canonical key Metabase writes and
|
|
210
|
+
is identical across forms. The `["ref", ["field", <id>, <opts>]]` form uses the
|
|
211
|
+
**legacy** field-ref order (id second); in the API form `<id>` is the numeric field id.
|
|
212
|
+
|
|
213
|
+
Per-column keys (apply under any column key):
|
|
214
|
+
|
|
215
|
+
| Key | Type | Values |
|
|
216
|
+
| ------------------- | ----------- | ------------------------------------------------------ |
|
|
217
|
+
| `column_title` | string | Override the column header |
|
|
218
|
+
| `number_style` | string | `"decimal"`, `"currency"`, `"percent"`, `"scientific"` |
|
|
219
|
+
| `currency` | string | ISO code, e.g. `"USD"` |
|
|
220
|
+
| `currency_style` | string | `"symbol"`, `"code"`, `"name"` |
|
|
221
|
+
| `number_separators` | string | e.g. `".,"` (decimal + thousands) |
|
|
222
|
+
| `decimals` | number | Fixed decimal places |
|
|
223
|
+
| `scale` | number | Multiply values by this factor |
|
|
224
|
+
| `prefix` / `suffix` | string | Affixes around the value |
|
|
225
|
+
| `date_style` | string | moment.js format, e.g. `"MMMM D, YYYY"` |
|
|
226
|
+
| `date_separator` | string | e.g. `"/"` |
|
|
227
|
+
| `date_abbreviate` | boolean | |
|
|
228
|
+
| `time_enabled` | string/null | `null`, `"minutes"`, `"seconds"`, `"milliseconds"` |
|
|
229
|
+
| `time_style` | string | e.g. `"HH:mm"`, `"h:mm A"` |
|
|
230
|
+
| `view_as` | string | `"link"`, `"image"`, `"email"`, `"auto"` |
|
|
231
|
+
| `link_text` | string | Display text when `view_as: link` |
|
|
232
|
+
| `link_url` | string | URL template; `{{value}}` interpolates the cell value |
|
|
233
|
+
| `click_behavior` | object | Per-column click behavior (see below) |
|
|
234
|
+
|
|
235
|
+
```yaml
|
|
236
|
+
column_settings:
|
|
237
|
+
'["name","TOTAL"]':
|
|
238
|
+
number_style: currency
|
|
239
|
+
currency: USD
|
|
240
|
+
currency_style: symbol
|
|
241
|
+
decimals: 2
|
|
242
|
+
column_title: "Total Revenue"
|
|
243
|
+
'["name","CREATED_AT"]':
|
|
244
|
+
date_style: "MMMM D, YYYY"
|
|
245
|
+
time_enabled: null
|
|
246
|
+
'["name","EMAIL"]':
|
|
247
|
+
view_as: link
|
|
248
|
+
link_text: "Send email"
|
|
249
|
+
link_url: "mailto:{{value}}"
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Virtual card settings (dashcards only, `card_id: null`)
|
|
253
|
+
|
|
254
|
+
| `virtual_card.display` | Extra keys |
|
|
255
|
+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
256
|
+
| `heading` | `text` (the heading string) |
|
|
257
|
+
| `text` | `text` (markdown; `{{param}}` placeholders wired via dashcard `parameter_mappings`, target `[text-tag, name]`) |
|
|
258
|
+
| `link` | `link.url`, or `link.entity` `{ id, model }` where model ∈ `question`/`dashboard`/`collection`/`database`/`table` |
|
|
259
|
+
| `iframe` | `iframe` (the `<iframe …>` HTML string) |
|
|
260
|
+
| `placeholder` | — |
|
|
261
|
+
|
|
262
|
+
```yaml
|
|
263
|
+
visualization_settings:
|
|
264
|
+
virtual_card:
|
|
265
|
+
display: text
|
|
266
|
+
text: "**Bold** and _italic_ markdown content"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Click behavior
|
|
270
|
+
|
|
271
|
+
Stored at `visualization_settings.click_behavior` (whole dashcard) or per column at
|
|
272
|
+
`column_settings[<key>].click_behavior`.
|
|
273
|
+
|
|
274
|
+
| `type` | Description |
|
|
275
|
+
| ------------- | -------------------------------------------- |
|
|
276
|
+
| `actionMenu` | Default drill-through menu (no config) |
|
|
277
|
+
| `crossfilter` | Filter the dashboard using the clicked value |
|
|
278
|
+
| `link` | Navigate to a URL, question, or dashboard |
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
# Link to URL — {{column}} = clicked row value, {{filter:param}} = dashboard parameter
|
|
282
|
+
click_behavior:
|
|
283
|
+
type: link
|
|
284
|
+
linkType: url
|
|
285
|
+
linkTemplate: "https://example.com/orders/{{ORDER_ID}}?status={{filter:status}}"
|
|
286
|
+
linkTextTemplate: "View Order {{ORDER_ID}}"
|
|
287
|
+
|
|
288
|
+
# Link to another dashboard/question — targetId is the entity_id of the target
|
|
289
|
+
click_behavior:
|
|
290
|
+
type: link
|
|
291
|
+
linkType: dashboard # or "question"
|
|
292
|
+
targetId: Q_jD-f-9clKLFZ2TfUG2h
|
|
293
|
+
parameterMapping:
|
|
294
|
+
target-param-uuid:
|
|
295
|
+
id: target-param-uuid
|
|
296
|
+
source: { id: USER_ID, name: User ID, type: column }
|
|
297
|
+
target: { id: target-param-uuid, type: parameter }
|
|
298
|
+
|
|
299
|
+
# Crossfilter — map a clicked column to dashboard parameters
|
|
300
|
+
click_behavior:
|
|
301
|
+
type: crossfilter
|
|
302
|
+
parameterMapping:
|
|
303
|
+
param-uuid:
|
|
304
|
+
id: param-uuid
|
|
305
|
+
source: { id: CATEGORY, name: Category, type: column }
|
|
306
|
+
target: { id: param-uuid, type: parameter }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
`parameterMapping` entries: `source` is where the value comes from
|
|
310
|
+
(`{ id, name, type }`, type `"column"`/`"parameter"`); `target` is where it goes
|
|
311
|
+
(`{ id, type }`, type `"parameter"`/`"dimension"`/`"variable"`). A `dimension` target
|
|
312
|
+
carries a `dimension` array — the same target shape as a dashboard parameter mapping.
|
|
@@ -76,8 +76,7 @@ fi
|
|
|
76
76
|
WS_ID=$(mb workspace create --name "$WS_NAME" --profile "$PARENT" --json | jq -r '.id')
|
|
77
77
|
|
|
78
78
|
# 2. Provision a database into it (blocks on :provisioned)
|
|
79
|
-
mb workspace database provision "$WS_ID" \
|
|
80
|
-
--database-id "$DB_ID" \
|
|
79
|
+
mb workspace database provision "$WS_ID" "$DB_ID" \
|
|
81
80
|
--schemas "$SCHEMAS" \
|
|
82
81
|
--wait \
|
|
83
82
|
--profile "$PARENT"
|
|
@@ -91,11 +90,10 @@ mb workspace start "$WS_ID" --wait --profile "$PARENT" "${REPO_FLAGS[@]}"
|
|
|
91
90
|
# This is the documented exception to "the agent doesn't run auth login" — the child
|
|
92
91
|
# key was minted by the parent the human authorized, and reading it via
|
|
93
92
|
# `workspace credentials` is the supported path.
|
|
94
|
-
WS_URL=$(mb workspace url "$WS_ID" --
|
|
95
|
-
WS_API_KEY=$(mb workspace credentials "$WS_ID" --
|
|
93
|
+
WS_URL=$(mb workspace url "$WS_ID" --json | jq -r '.url')
|
|
94
|
+
WS_API_KEY=$(mb workspace credentials "$WS_ID" --json | jq -r '.api_key')
|
|
96
95
|
printf '%s' "$WS_API_KEY" | mb auth login \
|
|
97
96
|
--url "$WS_URL" \
|
|
98
|
-
--api-key-stdin \
|
|
99
97
|
--profile "$WS_NAME" \
|
|
100
98
|
--json
|
|
101
99
|
|
|
@@ -106,24 +104,12 @@ mb database list --profile "$WS_NAME" --json
|
|
|
106
104
|
mb setting get remote-sync-url --profile "$WS_NAME" --json # → "file:///mnt/repo"
|
|
107
105
|
mb git-sync status --profile "$WS_NAME" --json # → branch, dirty, current task
|
|
108
106
|
|
|
109
|
-
# 7. (If REPO_FLAGS was set)
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
# `status: conflict` (stale task state from the boot-time import); retry once,
|
|
116
|
-
# then `--force` is safe because the workspace is empty (nothing to lose).
|
|
117
|
-
# Skipping the import entirely is *not* safe — without it the instance has none
|
|
118
|
-
# of the repo content and subsequent edits will diverge.
|
|
119
|
-
HOST_BRANCH=$(git -C "$(pwd)" symbolic-ref --short HEAD)
|
|
120
|
-
SYNC_STATUS=$(mb git-sync status --profile "$WS_NAME" --json)
|
|
121
|
-
if ! echo "$SYNC_STATUS" | jq -e --arg b "$HOST_BRANCH" \
|
|
122
|
-
'.current_task.sync_task_type == "import" and .current_task.status == "successful" and (.branch == $b)' >/dev/null; then
|
|
123
|
-
mb git-sync import --branch "$HOST_BRANCH" --profile "$WS_NAME" --json \
|
|
124
|
-
|| mb git-sync import --branch "$HOST_BRANCH" --profile "$WS_NAME" --json \
|
|
125
|
-
|| mb git-sync import --branch "$HOST_BRANCH" --force --profile "$WS_NAME" --json
|
|
126
|
-
fi
|
|
107
|
+
# 7. (If REPO_FLAGS was set) Apply the repo to the fresh workspace. The container's
|
|
108
|
+
# boot-time auto-import usually handles this — the step-6 `git-sync status` shows
|
|
109
|
+
# whether it landed. If `current_task` is not a successful `import` for the host
|
|
110
|
+
# branch, run an explicit import. The status-check + retry-then-force guard lives
|
|
111
|
+
# in the git-sync skill, "First import on a fresh workspace". Skipping the import is
|
|
112
|
+
# *not* safe — without it the instance has none of the repo content and edits diverge.
|
|
127
113
|
```
|
|
128
114
|
|
|
129
115
|
After step 5, drive the child via `mb <verb> --profile $WS_NAME` for everything (cards, transforms, queries, …). To author a transform on the workspace, load the `transform` skill (`mb skills get transform`). To use the sync flow (import host commits, export instance changes), load the `git-sync` skill (`mb skills get git-sync`).
|
|
@@ -145,13 +131,13 @@ Don't run `auth login` for them and don't suggest a URL — they pick. Verify wi
|
|
|
145
131
|
### 2. License
|
|
146
132
|
|
|
147
133
|
```bash
|
|
148
|
-
mb license status --
|
|
134
|
+
mb workspace license status --json
|
|
149
135
|
```
|
|
150
136
|
|
|
151
137
|
If `present: false`, ask the operator to run, themselves:
|
|
152
138
|
|
|
153
139
|
```bash
|
|
154
|
-
echo "<your-token>" | mb license set
|
|
140
|
+
echo "<your-token>" | mb workspace license set
|
|
155
141
|
```
|
|
156
142
|
|
|
157
143
|
A workspace child cannot start without a parent license — it inherits feature gates from the parent.
|
|
@@ -192,8 +178,7 @@ mb table list --db-id <db-id> --profile <parent> --json \
|
|
|
192
178
|
Provision (one db per call; `--schemas` is required, no "all" wildcard):
|
|
193
179
|
|
|
194
180
|
```bash
|
|
195
|
-
mb workspace database provision <ws-id> \
|
|
196
|
-
--database-id <db-id> \
|
|
181
|
+
mb workspace database provision <ws-id> <db-id> \
|
|
197
182
|
--schemas <schema1>,<schema2> \
|
|
198
183
|
--wait \
|
|
199
184
|
--profile <parent>
|
|
@@ -219,7 +204,7 @@ Before running `start`, ask the user about Remote Sync (see "Always ask about Re
|
|
|
219
204
|
Despite the `--port` flag's "auto-shifts up if taken" hint, in practice `workspace start` fails with `docker start failed for metabase-workspace-<id>` when the host port is occupied — typically by a stale workspace container from a prior session. **List local containers first** and pass an explicit free `--port`:
|
|
220
205
|
|
|
221
206
|
```bash
|
|
222
|
-
mb workspace ps
|
|
207
|
+
mb workspace ps # → currently-running workspace containers + their host ports
|
|
223
208
|
docker ps --filter "name=metabase-workspace" \
|
|
224
209
|
--format "{{.Names}}\t{{.Ports}}\t{{.Status}}" # also surfaces stopped containers
|
|
225
210
|
```
|
|
@@ -239,17 +224,15 @@ mb workspace start <ws-id> --repo /path/to/repo --repo-branch dev --repo-mode re
|
|
|
239
224
|
|
|
240
225
|
`--wait` blocks until `state: "running"`. Don't omit it for interactive bring-up — without it the next step (saving credentials as a child profile) races the container's HTTP listener and you'll get spurious connection errors.
|
|
241
226
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
| `--repo-branch <name>` | `remote-sync-branch` value. Default: current branch of the host repo (`git symbolic-ref --short HEAD`). |
|
|
252
|
-
| `--repo-mode <mode>` | `read-write` (default) or `read-only`. Also flips the bind mount's mount mode. |
|
|
227
|
+
- `--port <n>` — host port (default 3000; **does not** auto-shift reliably — pass an explicit free port if 3000 might be taken).
|
|
228
|
+
- `--wait` — block until `/api/health` reports ready before returning.
|
|
229
|
+
- `--no-pull` — skip `docker pull` (image already present).
|
|
230
|
+
- `--no-metadata` — skip the warehouse metadata export.
|
|
231
|
+
- `--force` — recreate even if a container for this workspace exists. Preserves the app db.
|
|
232
|
+
- `--timeout <ms>` — per-phase readiness deadline (default 240000). Covers the post-create config-consumption wait, (with `--wait`) the `/api/health` probe, and (with `--metadata`) the metadata-import status poll on the child. Bump if the first cold boot exceeds the default — image pull + JVM startup can stretch on slow disks/networks.
|
|
233
|
+
- `--repo <host-path>` — bind-mount a host directory at `/mnt/repo` and inject `remote-sync-url=file:///mnt/repo` into config.yml.
|
|
234
|
+
- `--repo-branch <name>` — `remote-sync-branch` value. Default: current branch of the host repo (`git symbolic-ref --short HEAD`).
|
|
235
|
+
- `--repo-mode <mode>` — `read-write` (default) or `read-only`. Also flips the bind mount's mount mode.
|
|
253
236
|
|
|
254
237
|
**Notes on `--repo`:**
|
|
255
238
|
|
|
@@ -264,21 +247,20 @@ mb workspace start <ws-id> --repo /path/to/repo --repo-branch dev --repo-mode re
|
|
|
264
247
|
`url` and `credentials` both return JSON envelopes. Extract fields with `jq`:
|
|
265
248
|
|
|
266
249
|
```bash
|
|
267
|
-
mb workspace url <ws-id> --
|
|
250
|
+
mb workspace url <ws-id> --json
|
|
268
251
|
# → {"workspace_id": ..., "url": "http://localhost:3000"}
|
|
269
252
|
|
|
270
|
-
mb workspace credentials <ws-id> --
|
|
253
|
+
mb workspace credentials <ws-id> --json
|
|
271
254
|
# → {"email": ..., "password": ..., "api_key": ...}
|
|
272
255
|
```
|
|
273
256
|
|
|
274
257
|
Save the child's API key as its own named profile. **Always pipe the key on stdin** (the CLI rejects `--api-key "$VAR"`).
|
|
275
258
|
|
|
276
259
|
```bash
|
|
277
|
-
WS_URL=$(mb workspace url <ws-id> --
|
|
278
|
-
WS_API_KEY=$(mb workspace credentials <ws-id> --
|
|
260
|
+
WS_URL=$(mb workspace url <ws-id> --json | jq -r '.url')
|
|
261
|
+
WS_API_KEY=$(mb workspace credentials <ws-id> --json | jq -r '.api_key')
|
|
279
262
|
printf '%s' "$WS_API_KEY" | mb auth login \
|
|
280
263
|
--url "$WS_URL" \
|
|
281
|
-
--api-key-stdin \
|
|
282
264
|
--profile <ws-name> \
|
|
283
265
|
--json
|
|
284
266
|
```
|
|
@@ -306,18 +288,18 @@ Log in with the **admin email + password** from `workspace credentials` (the API
|
|
|
306
288
|
|
|
307
289
|
## Lifecycle
|
|
308
290
|
|
|
309
|
-
| User intent | Command
|
|
310
|
-
| --------------------------------- |
|
|
311
|
-
| List local workspace containers | `mb workspace ps
|
|
312
|
-
| Tail logs | `mb workspace logs <ws-id> --tail 200
|
|
313
|
-
| Follow logs | `mb workspace logs <ws-id> --follow
|
|
314
|
-
| Read admin email/password/API key | `mb workspace credentials <ws-id> --
|
|
315
|
-
| Stop (preserves app db) | `mb workspace stop <ws-id
|
|
316
|
-
| Restart | `mb workspace start <ws-id> --force --wait --profile <parent>`
|
|
317
|
-
| Remove container + app db | `mb workspace
|
|
318
|
-
| Remove container, keep app db | `mb workspace
|
|
291
|
+
| User intent | Command |
|
|
292
|
+
| --------------------------------- | -------------------------------------------------------------- |
|
|
293
|
+
| List local workspace containers | `mb workspace ps` |
|
|
294
|
+
| Tail logs | `mb workspace logs <ws-id> --tail 200` |
|
|
295
|
+
| Follow logs | `mb workspace logs <ws-id> --follow` |
|
|
296
|
+
| Read admin email/password/API key | `mb workspace credentials <ws-id> --json` |
|
|
297
|
+
| Stop (preserves app db) | `mb workspace stop <ws-id>` |
|
|
298
|
+
| Restart | `mb workspace start <ws-id> --force --wait --profile <parent>` |
|
|
299
|
+
| Remove container + app db | `mb workspace delete <ws-id> --yes` |
|
|
300
|
+
| Remove container, keep app db | `mb workspace delete <ws-id> --keep-volume --yes` |
|
|
319
301
|
|
|
320
|
-
The supported restart path is `stop` + `start --force` (or `start --force` directly). The app db volume persists across `stop`/`start` cycles, so users/sessions/saved questions survive. `
|
|
302
|
+
The supported restart path is `stop` + `start --force` (or `start --force` directly). The app db volume persists across `stop`/`start` cycles, so users/sessions/saved questions survive. `delete`, `start --force`, and `stop` are destructive enough to confirm before running unless the user explicitly asked for them.
|
|
321
303
|
|
|
322
304
|
## Diagnose
|
|
323
305
|
|
|
@@ -326,14 +308,14 @@ Pick the symptom.
|
|
|
326
308
|
### `start` succeeds but the database isn't visible in the UI
|
|
327
309
|
|
|
328
310
|
```bash
|
|
329
|
-
mb workspace logs <ws-id> --tail 300
|
|
311
|
+
mb workspace logs <ws-id> --tail 300 | grep -iE "advanced-config|workspace|error"
|
|
330
312
|
```
|
|
331
313
|
|
|
332
314
|
| Log signal | Cause | Fix |
|
|
333
315
|
| ---------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
334
316
|
| `Spec assertion failed ... :input ... :output` | Parent emits keys the child's spec doesn't accept (server-side). | File against the parent. Not a CLI issue. |
|
|
335
317
|
| `Connection refused` / `unknown host` against the warehouse host | Container can't reach the source DB. | Source DB credentials configured on the parent use a host that doesn't resolve from inside docker. Use a routable hostname. |
|
|
336
|
-
| `Invalid token` / `License expired` | EE license bad or unset on the parent (forwarded into the child). | Re-set on the parent: `mb license set` (operator pastes).
|
|
318
|
+
| `Invalid token` / `License expired` | EE license bad or unset on the parent (forwarded into the child). | Re-set on the parent: `mb workspace license set` (operator pastes). |
|
|
337
319
|
|
|
338
320
|
### `workspace credentials` returns values that don't authenticate
|
|
339
321
|
|
|
@@ -344,20 +326,20 @@ This is a parent↔child credential drift bug — the parent's record for the wo
|
|
|
344
326
|
Recovery (works reliably):
|
|
345
327
|
|
|
346
328
|
```bash
|
|
347
|
-
mb workspace
|
|
329
|
+
mb workspace delete <ws-id> --yes # destroys container + volume; keeps parent record + provisioned dbs
|
|
348
330
|
mb workspace start <ws-id> --port <fresh-port> --wait --profile <parent> # different port from the bad attempt
|
|
349
|
-
mb workspace credentials <ws-id> --
|
|
331
|
+
mb workspace credentials <ws-id> --json | jq -r '.api_key' \
|
|
350
332
|
| xargs -I{} curl -s -H "x-api-key: {}" http://localhost:<fresh-port>/api/user/current # smoke check
|
|
351
333
|
```
|
|
352
334
|
|
|
353
|
-
Why "different port": empirically, restarting on the same port after the drifted attempt can cling to the same broken state; switching ports forces a clean parent-side handoff. If you must reuse the original port, `workspace
|
|
335
|
+
Why "different port": empirically, restarting on the same port after the drifted attempt can cling to the same broken state; switching ports forces a clean parent-side handoff. If you must reuse the original port, `workspace delete --yes` plus a brief pause (a few seconds) before `start` increases the success rate.
|
|
354
336
|
|
|
355
|
-
`workspace
|
|
337
|
+
`workspace delete --yes` is destructive — it drops the container _and_ the app db volume — but in the bring-up window (before any user content has been imported) there's nothing to lose. The provisioned-database records on the parent survive the delete and don't need to be re-created.
|
|
356
338
|
|
|
357
339
|
### Container exited shortly after `start`
|
|
358
340
|
|
|
359
341
|
```bash
|
|
360
|
-
mb workspace ps
|
|
342
|
+
mb workspace ps
|
|
361
343
|
```
|
|
362
344
|
|
|
363
345
|
`Exited (137)` → OOM. Bump Docker host memory to ≥ 6 GB.
|
|
@@ -392,7 +374,7 @@ mb workspace list --profile <parent> --full --json \
|
|
|
392
374
|
|
|
393
375
|
### Workspace UI demands the setup wizard
|
|
394
376
|
|
|
395
|
-
You opened the URL before health passed and walked through the wizard, which created a fresh app db and bypassed the workspace bring-up. `mb workspace
|
|
377
|
+
You opened the URL before health passed and walked through the wizard, which created a fresh app db and bypassed the workspace bring-up. `mb workspace delete <ws-id> --yes` then `start --wait` again. Don't open the URL before `state: "running"`.
|
|
396
378
|
|
|
397
379
|
### `git status` on the host shows confusing "staged changes" after `git-sync export`
|
|
398
380
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: metabase-cli
|
|
3
|
-
description: Drive a Metabase instance from the terminal via the `mb` CLI
|
|
4
|
-
allowed-tools: Bash
|
|
3
|
+
description: Drive a Metabase instance from the terminal via the `mb` CLI — auth, databases, cards, dashboards, transforms, queries, search, git-sync, Enterprise workspaces. Discovery entry; load the full guide with `mb skills get core`.
|
|
4
|
+
allowed-tools: Bash, Read, Write, Edit, AskUserQuestion
|
|
5
5
|
hidden: true
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -13,30 +13,9 @@ Install: `npm i -g @metabase/cli`
|
|
|
13
13
|
|
|
14
14
|
## Start here
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Before running any `mb` command, load the workflow content from the CLI:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
mb skills get core
|
|
20
|
-
mb skills
|
|
19
|
+
mb skills get core # auth, flag conventions, every command group
|
|
20
|
+
mb skills list # everything available on the installed version
|
|
21
21
|
```
|
|
22
|
-
|
|
23
|
-
The CLI serves skill content bundled with the installed version, so instructions never go stale. The content in this stub cannot change between releases, which is why it just points at `mb skills get core`.
|
|
24
|
-
|
|
25
|
-
## Specialized skills
|
|
26
|
-
|
|
27
|
-
Load a specialized skill when the task falls outside one-shot CLI use:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
mb skills get workspace # Enterprise workspaces: create, provision, start, child credentials, diagnose
|
|
31
|
-
mb skills get transform # author + run transforms (native SQL and MBQL 5), iterate on failures
|
|
32
|
-
mb skills get git-sync # round-trip Metabase content to/from a git remote
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Run `mb skills list` to see everything available on the installed version.
|
|
36
|
-
|
|
37
|
-
## Why mb
|
|
38
|
-
|
|
39
|
-
- Native `fetch`, typed Zod schemas, redacted secrets — the supported path for Metabase REST automation.
|
|
40
|
-
- One `--profile` per command targets staging, prod, a workspace child, whatever the user has configured.
|
|
41
|
-
- Output is shaped for agents: compact projection by default, `--full` / `--fields a,b.c` / `--json` / `--max-bytes` on every list/get.
|
|
42
|
-
- `mb __manifest` returns the canonical, machine-readable inventory of every command — name, args, output schema. Use it instead of scraping `--help`.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import "./package-DFUprkSZ.mjs";
|
|
2
|
-
import "./command-augment-D9pI9Vbh.mjs";
|
|
3
|
-
import "./render-DuoDUTVL.mjs";
|
|
4
|
-
import "./predicates-CGO17Q15.mjs";
|
|
5
|
-
import "./runtime-CDu6fykq.mjs";
|
|
6
|
-
import "./parse-id-CysSaCbf.mjs";
|
|
7
|
-
import "./poll-task-BQe0NvJZ.mjs";
|
|
8
|
-
import "./poll-p9Y7-JEQ.mjs";
|
|
9
|
-
import { SyncSettingsUpdateResult, add_collection_default, setCollectionRemoteSynced, syncSettingsUpdateView } from "./add-collection-C_iovi9i.mjs";
|
|
10
|
-
|
|
11
|
-
export { add_collection_default as default };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineCommand } from "citty";
|
|
2
|
-
|
|
3
|
-
//#region src/commands/api-key/index.ts
|
|
4
|
-
var api_key_default = defineCommand({
|
|
5
|
-
meta: {
|
|
6
|
-
name: "api-key",
|
|
7
|
-
description: "Manage Metabase API keys"
|
|
8
|
-
},
|
|
9
|
-
subCommands: { create: () => import("./create-CrUq6sib.mjs").then((mod) => mod.default) }
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
export { api_key_default as default };
|
package/dist/auth-DICRtJDy.mjs
DELETED
|
@@ -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-D1nZwgKv.mjs").then((m) => m.default),
|
|
12
|
-
status: () => import("./status-1oUnw803.mjs").then((m) => m.default),
|
|
13
|
-
list: () => import("./list-DV6CONhp.mjs").then((m) => m.default),
|
|
14
|
-
logout: () => import("./logout-DD4q5whi.mjs").then((m) => m.default)
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
export { auth_default as default };
|