Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 48 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,38 +469,7 @@ mb table update 42 --file patch.json
echo '{"description":"Customer dimension"}' | mb table update 42
```

### `mb table publish`

Publish tables to a library collection (`POST /api/ee/data-studio/table/publish-tables`), surfacing them as trusted data sources. The selected tables and every upstream table they depend on are set to the target `library-data` collection. Select tables with `--table-ids`, whole databases with `--db-ids`, or schemas with `--schemas` — the filters are combined. Requires the `library` premium feature.

```sh
mb table publish --collection-id 12 --table-ids 1,2,3
mb table publish --collection-id 12 --db-ids 1 --json
mb table publish --collection-id 12 --schemas 1:public,1:analytics
```

| Flag | Description |
| ---------------------- | ----------------------------------------------------------------- |
| `--collection-id <id>` | Target library collection id (required). |
| `--table-ids <ids>` | Comma-separated table ids. |
| `--db-ids <ids>` | Comma-separated database ids. |
| `--schemas <ids>` | Comma-separated schema ids, each `<db-id>:<schema>` (`1:public`). |

### `mb table unpublish`

Unpublish tables from the library (`POST /api/ee/data-studio/table/unpublish-tables`). Clears the library collection for the selected tables and every downstream table that depends on them. Same selector flags as `publish` (minus `--collection-id`). Requires the `library` premium feature.

```sh
mb table unpublish --table-ids 1,2,3
mb table unpublish --db-ids 1 --json
mb table unpublish --schemas 1:public,1:analytics
```

| Flag | Description |
| ------------------- | ----------------------------------------------------------------- |
| `--table-ids <ids>` | Comma-separated table ids. |
| `--db-ids <ids>` | Comma-separated database ids. |
| `--schemas <ids>` | Comma-separated schema ids, each `<db-id>:<schema>` (`1:public`). |
Publish status surfaces on the table itself — `table get`/`table list` carry `is_published` (and `collection_id` under `--full`). Publishing tables to the Library is done with [`mb library publish`](#library).

## Fields

Expand Down Expand Up @@ -991,6 +960,53 @@ mb collection archive 4
mb collection archive 4 --json
```

## Library

Curate the Metabase **Library** — a governed subtree (`library-data` "Data" for published tables, `library-metrics` "Metrics" for official metrics, under a `library` root). Tables published to Data appear first when people pick a data source and rank up in search, steering everyone toward trusted, analysis-ready tables. Requires the `library` premium feature (Pro/Enterprise) and admin or data-analyst permission (Curate alone won't publish tables). Publish status surfaces on the table via `is_published` (`table get`/`table list`).

### `mb library get`

Show the Library and its Data/Metrics collection ids (`GET /api/ee/library/`). Errors if the Library hasn't been created yet.

```sh
mb library get
mb library get --json
```

### `mb library create`

Create the Library subtree (`POST /api/ee/library/`). Idempotent — returns the existing Library when it's already there.

```sh
mb library create
mb library create --json
```

### `mb library publish`

Publish tables (and their upstream dependencies) into the Library's Data collection (`POST /api/ee/data-studio/table/publish-tables`). The target Data collection is resolved automatically and the Library is created if it doesn't exist yet — there's no collection id to pass.

```sh
mb library publish --table-ids 1,2,3
mb library publish --db-ids 1 --json
mb library publish --schemas 1:public,1:analytics
```

| Flag | Description |
| ------------------- | ----------------------------------------------------------------- |
| `--table-ids <ids>` | Comma-separated table ids. |
| `--db-ids <ids>` | Comma-separated database ids. |
| `--schemas <ids>` | Comma-separated schema ids, each `<db-id>:<schema>` (`1:public`). |

### `mb library unpublish`

Unpublish tables (and their downstream dependents) from the Library (`POST /api/ee/data-studio/table/unpublish-tables`). Same selector flags as `publish`.

```sh
mb library unpublish --table-ids 1,2,3
mb library unpublish --db-ids 1 --json
```

## Documents

CRUD on `/api/document`. A document is a rich-text page that mixes prose with embedded saved questions (`cardEmbed`) and inline links to Metabase entities (`smartLink`). The body is a [TipTap](https://tiptap.dev/) (ProseMirror) JSON tree stored under `content_type: application/json+vnd.prose-mirror`. The agent-facing format reference lives in the bundled `document` skill (`mb skills get document`). It's a baseline OSS feature — no elevated server version or premium token required.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@metabase/cli",
"version": "0.1.15",
"version": "0.1.16",
"description": "Metabase CLI",
"license": "AGPL-3.0",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions skill-data/core/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The official Metabase CLI (`mb`) drives a Metabase instance over its REST API: a
Top-level command groups (run `mb <group> --help` to discover verbs):

```
auth | db | table | field | query | card | dashboard | snippet | segment | measure | collection
auth | db | table | field | query | card | dashboard | snippet | segment | measure | collection | library
document | transform | transform-job | transform-tag | setting | search | git-sync | setup | eid | uuid | upgrade | skills
```

Expand Down Expand Up @@ -128,7 +128,7 @@ Routine verb shapes (list / get / create / update), every flag, and output JSON

- **db traversal vs. rollup.** Default to granular: `database list` → `database schemas <db-id>` → `database schema-tables <db-id> <schema>` → `table get <table-id> --include fields`. The rollup endpoints (`database get --include tables.fields`, `database metadata <db-id>`) pull megabytes and blow the context window on any real warehouse — use them only on a small/dev db. `sync-schema` / `rescan-values` queue async work and return `{status:"ok"}` immediately; `sync-schema --wait` blocks until `initial_sync_status: complete`.
- **table fields.** `table get` never returns fields on its own — pass `--include fields` (compact) or use `table fields <id>` (list envelope). `table metadata <id>` adds FKs + dimensions (heavier). `table update` patches table-level metadata only; physical columns aren't editable here.
- **table publish / unpublish.** EE-only (`library` premium feature, v59+) bulk Library curation. Pick targets with `--table-ids` / `--db-ids` / `--schemas` (combined as OR), where each `--schemas` entry is `<db-id>:<schema>` (e.g. `1:public`), **not** a bare schema name. `publish --collection-id` must point at a `library-data` collection (a regular collection is rejected with a 400). `publish` cascades to upstream FK dependencies, `unpublish` to downstream dependents; both exit **403** unless you have write **and** query permission on every affected table.
- **library.** EE-only (`library` premium feature, v59+). The Library is a curated subtree (`library-data` "Data" + `library-metrics` "Metrics" under a `library` root): tables published to **Data** appear first in data pickers and rank up in search; metrics saved to **Metrics** are prioritized in nav, search, and the query builder. So the Library is how you tell people (and agents) "start from these — they're trusted." `library get` shows the Library and its Data/Metrics collection ids; `library create` provisions it (idempotent). `library publish --table-ids/--db-ids/--schemas` publishes tables into Data — it **resolves the Data collection itself and creates the Library if absent** (no collection id to find); each `--schemas` entry is `<db-id>:<schema>` (e.g. `1:public`), not a bare name. `publish` cascades to upstream FK dependencies, `unpublish` to downstream dependents; both need **admin or data-analyst** (Curate permission alone won't publish tables) and exit **403** without write **and** query permission on every affected table. Publish status shows on the table: `table get`/`table list` carry `is_published` (`collection_id` under `--full`). Good candidates are finished, analysis-ready tables — clean/combine via transforms first, then publish the polished result; don't publish raw tables.
- **field has no `list`.** Fields are per-table — get them via `table get <id> --include fields`. Never enumerate fields across a whole db (context blow-up). `field summary` is live cardinality `{field_id, count, distincts}`; `field values` is the cached distinct set (`has_more_values: true` ⇒ truncated cache). `field update` patches metadata only; `base_type` isn't editable.
- **card.** `dataset_query` is the **flat** `mbql/query` value, not a legacy `{type:"query",query:…}` envelope (→ `mbql` skill). `--export-format csv|xlsx` streams the raw export (pipe to a file), bypassing the JSON envelope. `archive` is the only delete; unarchive with `update --body '{"archived":false}'`. `visualization_settings` keys are scoped by `display` and aren't pre-flighted — see the `viz` skill.
- **dashboard.** Dashcards round-trip through `PUT /api/dashboard/:id` (no per-dashcard endpoint): `update-dashcard <dash-id> <dashcard-id>` patches one safely; `update --body '{"dashcards":[…]}'` replaces the whole set (omitted ids are deleted server-side; negative ids for new cards). `create` accepts the **same** `dashcards` array in its initial body — lay out the whole dashboard in one call: negative ids for new cards, and `card_id:null` plus a `visualization_settings.virtual_card` block (`{display:"text"|"heading"|"link"|…}`) for non-question cards. `create`/`update` pre-flight every positive `card_id` against live server state and exit **2** with `{ok:false,errors:[…]}` on a bad ref — non-bypassable (no `--skip-validate`). `dashboard get <id>` (or `--full`) hydrates dashcards/tabs; `list` omits them. **Dashcard geometry: the grid is 24 columns wide.** Each dashcard's `{col, row, size_x, size_y}` is in grid units — `col` (0-indexed, left edge) and `size_x` are columns, `row`/`size_y` are rows; **full-width is `size_x: 24`** (`size_x: 12` is half a row — the usual cause of a card filling only half the width, since it's a common per-chart default). Keep `col + size_x ≤ 24`, start each card's `col` at 0 for a full-width stack, and don't overlap cards (the server stores whatever you send — it won't auto-fix collisions).
Expand Down
Loading
Loading