关于 metabase
Metabase Skill 是用于构建、编辑、测试和管理 Metabase BI 内容的 Node.js 命令行工具集,支持基于文件的仪表板项目、SQL 与卡片操作、可视化渲染和受控发布。
主要功能
- 01以文件形式创建并校验仪表板项目
- 02查询、导出和管理卡片及 SQL
- 03将仪表板和卡片渲染为图片或 PDF
- 04管理提醒、订阅、用户和权限
- 05更新前检查变更和历史记录
适用场景
- 01发布前构建并目视检查仪表板
- 02通过项目文件维护仪表板定义
- 03导出查询结果或渲染仪表板以便分享
- 04检查权限或恢复较早的仪表板版本
MCP 相关
该技能未被描述为 MCP 服务或客户端。README 提到,Metabase 管理界面中的 Admin > AI > MCP 会影响浏览器登录的应用注册。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ onsen-ai/ metabase-skill --skill metabase安装后在 Claude Code 中输入/metabase确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoreREADME.mdpackage.jsonassets/templates/design-doc.mdmockup-text-template.mdmockup-html-template.htmlevals/evals.jsonevals-write.jsonscripts/lib/args.mjsclient.mjsconfirm.mjsscripts/lib/auth/callback-server.mjsoauth.mjssession.mjstoken-store.mjspkce.mjsscripts/lib/commands/auth.mjsdashboard.mjsdiscover.mjscard.mjscollection.mjshistory.mjsmetadata.mjsproject-sync.mjspivot.mjssetup.mjsnotify.mjssnippet.mjsproject.mjspermissions.mjs详细介绍
Metabase Skill
面向 Metabase 的端到端 BI 开发工具:设计仪表板、编写和测试 SQL、将仪表板保存为文件、发布仪表板、查看结果,以及分享或安排发送。
所有脚本都位于 ${CLAUDE_SKILL_DIR}/scripts/,只需要 Node.js(无需 npm install;渲染需要 Node 22+ 和 Google Chrome)。以下每条命令都是 node ${CLAUDE_SKILL_DIR}/scripts/metabase.mjs <command>。
首次设置
运行 instances,查看有哪些 Metabase 连接(不会显示密钥或令牌)。切勿读取 ~/.metabase-skill/config.json 或 ~/.metabase-skill/tokens/ 下的任何内容——其中可能包含机密信息。
- **已列出实例:**使用这些实例(有多个时,询问用户要使用哪一个)。
status会显示登录用户、登录方式、Metabase 版本,以及是否为免费版。 - **未配置任何实例:**请用户在自己的终端中登录(这会打开浏览器;你无法代为操作):
node ${CLAUDE_SKILL_DIR}/scripts/metabase.mjs login --instance <name> --url https://metabase.example.com
浏览器登录(Metabase v63+)使用用户自己的 Metabase 账户和权限;令牌会保存到 macOS Keychain(位于其他位置的私有文件中),并自动续期。API 密钥仍可用于脚本和 CI:使用 setup → env 或 direct 模式。如果 login 提示应用注册已关闭,说明管理员禁用了 Admin > AI > MCP(这也会关闭自动注册):请重新启用,或注册应用并传入 --client-id。
快速参考
全局选项(适用于每条命令):
--instance <name>— 使用非默认连接--json— 输出 JSON(列表/发现类命令不加此选项时会输出文本表格;获取/创建/更新类命令始终输出 JSON)--fields <a,b.c>— 仅输出 JSON 结果中的这些点路径字段(列表中针对每个项目),例如card 402 --fields name,dataset_query.stages.0.native--max-bytes <n>— 限制输出的 JSON 大小(默认 24576,0= 不限制)。列表会截断并显示提示;如果对象过大,则拒绝输出(退出码 2)——请使用--fields缩小范围,或使用--out--skip-preflight— 在不具备相关功能的实例上尝试仅限 Pro/Enterprise 的命令--theme light|dark— Chrome 渲染图片时使用的配色方案(默认 light;否则 Metabase 会沿用操作系统设置)
退出码:0 成功,1 操作失败,2 输入/预检问题(修正输入;提示信息会说明原因)。
登录
| 命令 | 功能 |
|---|---|
login --instance <n> --url <u> [--client-id <id>] | 浏览器登录(v63+);创建连接 |
logout [--instance <n>] | 撤销并删除已保存的登录信息 |
status [--instance <n>] | 用户、身份验证方式、令牌到期时间、Metabase 版本、版本类型 |
setup / instances | 设置向导(浏览器或 API 密钥)/ 列出连接 |
项目 — 以 YAML + SQL 文件构建的仪表板(参见 specs/project-format.md)
| 命令 | 功能 |
|---|---|
project new <dir> --name <n> --database <id> [--collection <id>] | 为新仪表板创建空项目文件夹 |
project pull <dir> [--dashboard <id> [--loose-cards] | --collection <id>] [--force] | Metabase → 文件(首次拉取需要 --dashboard 或 --collection;--loose-cards 还会保留集合中不属于任何仪表板的卡片;如果本地有编辑内容,则拒绝覆盖) |
project validate <dir> [--json] | 检查结构、引用、24 列网格、筛选器连接、SQL 标签和图表设置 |
project lint <dir> [--strict] [--offline] | 设计检查(描述、数字格式、完整行、未连接的筛选器,…) |
project diff <dir> [--json] | 精确列出推送会进行的更改,逐字段、逐位置呈现 |
project status <dir>... [--json] | 检查这些文件夹中及其下的所有项目:已同步、在 Metabase 中有更改(拉取),或尚未推送(推送)。只读 |
project push <dir> [--dry-run] [--yes] | 文件 → Metabase(片段、卡片、仪表板、订阅);检测到偏差时会发出警告 |
project test <dir> [--card <key>] [--images] | 使用仪表板的默认筛选器运行所有卡片(与文件中的定义一致);--images → PNG 图片 |
project render <dir> [--pdf] [--tab <name>] | 将已发布的仪表板渲染为图片 / PDF → <dir>/.mbsync/render/ |
图片和 PDF(参见 specs/rendering.md)
| 命令 | 功能 |
|---|---|
card image <id> [--out f.png|f.pdf] [--params <json>] [--width N --height N] | 已保存问题的图表(卡片级设置,不含仪表板筛选器) |
dashcard image <dashboard-id> <index|name> [--id] [--out ..] [--params <json>] | 查看仪表板上的单个图块:包括其标题、值、格式和仪表板筛选器 |
dashboard render <id> [--out f.png|f.pdf] [--tab <name|id>] [--params <json>] | 渲染所有标签页(每个标签页生成一张 PNG,或生成一个 PDF);报告显示错误的卡片 |
dashboard render <id> --server [--out f.pdf] [--paper a4|letter] | 由 Metabase 自行绘制的 PDF(v63+,订阅样式);无需 Chrome |
发现
| 命令 | 功能 |
|---|---|
databases / tables --database <id> | 数据库 / 表及字段 |
collections [--tree] / collection-items <id> [--models card,dashboard] | 集合(★ = 官方)/ 内容 |
search <query> [--models ...] | 按名称查找任意内容 |
卡片(问题)
| 命令 | 功能 |
|---|---|
card <id> | 摘要:结果列、片段、模板标签 |
card <id> --full --out <file> / --layout --out <file> | 将完整负载 / 可写字段输出到文件 |
card create --from <file> [--skip-validate] | 创建(先检查:标签、字段筛选器、编译、图表设置) |
card update <id> --patch <file> [--skip-validate] | 获取 → 合并 → 检查 → 保存 |
card delete <id> [--permanent --yes] / card restore <id> | 归档(可恢复)/ 永久删除 / 取消归档 |
card copy <id> [--collection <id>] | 复制 |
card query <id> [--params '{"tag": value}'] [--out <file>] | 运行查询(20 行,或将所有行输出到文件) |
card query <id> --export csv|json|xlsx --out <file> [--params ..] | 下载结果 |
card history <id> / card revert <id> --to <revision-id> [--yes] | 查看谁改了什么 / 恢复某个版本 |
pivot build --table <id> --rows <f[:unit],..> [--columns ..] --values <count|sum:F,..> (--out f.json | --project <dir> --key <k>) | 编写正确的结构化透视表问题(运行一次进行检查) |
仪表板
| 命令 | 功能 |
|---|---|
dashboard <id> | 摘要:标签页、筛选器、放置项、repeated_card_ids、每个放置项的 overrides |
dashboard <id> --layout --out <file> / --full --out <file> | 仅布局(30 张卡片约 3K 个令牌)/完整载荷 |
dashboard create --from <file> | 创建空壳 |
dashboard put <id> --from <file> [--skip-validate] | 保存整个布局(会先检查每个引用的卡片) |
dashboard update <id> --patch <file> | 获取 → 合并 → 保存 |
dashcard <dashboard-id> <index|name> [--id] | 单个放置项的设置和筛选器连接 |
dashcard update <dashboard-id> <index|name> [--id] --patch <file> | 修改单个放置项;其余保持不变 |
dashboard delete <id> [--permanent --yes] / dashboard restore <id> | 归档 / 永久删除 / 取消归档 |
dashboard copy <id> [--collection <id>] | 复制 |
dashboard history <id> / dashboard revert <id> --to <revision-id> | 查看修改者和修改内容 / 恢复到某个版本 |
警报和订阅(参见 specs/notifications-api-spec.md)
| 命令 | 功能 |
|---|---|
alerts [--card <id>] / alert <id> | 列出 / 显示卡片警报 |
alert create --from <file> / alert update <id> --patch <file> | 为卡片设置警报(条件 + Quartz cron + 收件人) |
alert archive <id> / alert restore <id> / alert send <id> [--yes] | 停止 / 恢复 / 立即发送给真实收件人 |
subscriptions [--dashboard <id>] / subscription <id> | 列出 / 显示仪表板订阅 |
subscription create --from <file> / subscription update <id> --patch <file> | 按计划通过邮件/Slack 发送仪表板 |
subscription archive <id> / subscription restore <id> | 停止 / 恢复 |
代码片段、集合、元数据
| 命令 | 功能 |
|---|---|
snippets / snippet <id> | 列出 / 显示 SQL |
snippet create --name <n> --content <sql> [--collection <id>] [--description <d>] | 创建 |
snippet update <id> [--name] [--content] [--description] [--archived true|false] | 更新或归档(不能永久删除) |
collection create --name <n> [--parent <id>] [--description <d>] | 创建 |
collection update <id> [--name] [--parent] [--description] [--archived true|false] | 重命名、移动、归档 |
database sync-schema <id> / field rescan-values <id> / field discard-values <id> | 获取新列 / 刷新下拉值 |
用户、群组、权限
users [--query --status --admins --group <ids> --groups-all <ids>]、user <id>|create|update|deactivate、
groups、group <id>|create|delete|add-user|remove-user、permissions [--database] [--group] [--native-sql] [--collections]、permissions summary、permissions set … [--dry-run] [--yes]、permissions set-collection …。
仅限 Pro/Enterprise(免费版会提前拒绝):usage-analytics …、sandboxes、sandbox create|delete、
permissions app [set]、permissions set-snippets、collection … --authority-level official。
--help 会打印所有命令和标志。
上下文安全规则
必须遵守:
- 绝不将完整的仪表板/卡片载荷加载到上下文中。 使用摘要(
card <id>、dashboard <id>)、用--fields获取单个部分,或使用--full --out <file>。 - 绝不打印或读取机密信息。 输出中绝不会出现 API 密钥和令牌;不要读取
config.json或tokens/。 - 发送任何内容都要使用文件。
--from/--patch接受项目目录中的文件路径,绝不要使用/tmp。 - 判断图表时看图片,而不是载荷。 使用
card image/dashboard render,再用 Read 读取 PNG。
何时询问用户
你负责构建;用户负责决策。选择以下内容时,请提问(AskUserQuestion):实例;仪表板的用途和受众;指标和维度;布局(标签页、排列方式、图表类型);筛选器(选择哪些、默认值、级联);不确定时选择 SQL 还是 MBQL;有多个有效选项时的可视化方案;在 Metabase 中创建或更改任何内容之前(展示计划或 project diff);向实际收件人发送任何内容之前(alert send、新订阅——确认地址);以及任何意外失败时(报告问题;不要悄悄重试)。
任务识别
| 模式 | 适用情况 | 工作流 |
|---|---|---|
| NEW | 构建仪表板 | 设计 → 项目文件 → 验证/检查 → 推送 → 视觉检查 |
| EDIT (project) | 更改保存在项目文件夹中的仪表板 | 拉取 → 编辑文件 → diff → 推送 → 视觉检查 |
| EDIT (direct) | 快速更改未以文件形式保存的仪表板 | STUDY → 通过卡片/仪表板卡片命令更改 → 视觉检查 |
| STUDY | 了解仪表板(描述、审计、规划更改) | 摘要 → 渲染 → 逐卡检查 → 覆盖项审计 |
| SHARE & SCHEDULE | 为他人生成 PDF/PNG、设置提醒、订阅 | 渲染 / 提醒 / 订阅 |
| EXPLORE / REORGANIZE | 浏览、搜索、移动、重命名 | 发现和集合命令 |
| HISTORY | “谁改了这个”“恢复原状” | history → 确认 → revert |
| USAGE-ANALYTICS | 采用情况、过时内容、查询性能(Pro/Enterprise) | 针对分析模型使用 MBQL |
| ADMIN | 用户、群组、权限 | 权限命令 |
已有项目文件夹(包含 project.yaml 和 ids.json)的仪表板,始终应通过项目进行编辑:直接在 Metabase 中编辑会导致文件过时(推送时会提示存在差异)。
参考资料加载策略
选择模式后,开始前请阅读对应资料包中的每份规范。延迟读取会导致请求负载错误。
| 模式 | 规范(${CLAUDE_SKILL_DIR}/specs/…) |
|---|---|
| NEW / EDIT / STUDY | project-format.md、rendering.md、dashboard-api-spec.md、card-api-spec.md、visualization-cookbook.md、sql-style-guide.md、snippet-api-spec.md、discovery-api-spec.md |
| SHARE & SCHEDULE | rendering.md、notifications-api-spec.md |
| EXPLORE / REORGANIZE | discovery-api-spec.md、collection-api-spec.md、card-api-spec.md |
| 独立 SQL / 卡片 / 片段 | card-api-spec.md、sql-style-guide.md、snippet-api-spec.md、visualization-cookbook.md |
| USAGE-ANALYTICS | usage-analytics-spec.md |
| ADMIN | permissions-api-spec.md、permissions-guide.md |
资源(${CLAUDE_SKILL_DIR}/assets/templates/):mockup-text-template.md、mockup-html-template.html、
design-doc.md —— 在设计阶段按需加载。
| 规范 | 内容 |
|---|---|
project-format.md | 项目文件夹格式、派生内容、推送/拉取行为、检查规则 |
rendering.md | 卡片/仪表板图片和 PDF 的生成方式、选项、输出、限制 |
notifications-api-spec.md | 提醒与订阅、正文、计划、注意事项 |
dashboard-api-spec.md | 仪表板 CRUD、布局、参数、映射目标、PUT 规则 |
card-api-spec.md | 卡片 CRUD、MBQL、本地 SQL、模板标签、v63 的返回内容 |
visualization-cookbook.md | 各种显示方式所需的设置和尺寸;可复制粘贴的示例 |
sql-style-guide.md | SQL 约定、示例数据库的方言 |
snippet-api-spec.md / collection-api-spec.md / discovery-api-spec.md | 片段 / 集合 / 元数据与搜索 |
permissions-api-spec.md / permissions-guide.md | 用户、群组、权限图 / 操作指南与安全性 |
usage-analytics-spec.md | 分析模型、MBQL 模式(Enterprise) |
NEW 仪表板工作流
开始之前
询问:选择 先设计(推荐用于 5 张以上卡片、标签页或复杂筛选器)还是 直接构建(简单需求)?
然后商定 项目文件夹(例如 <repo>/dwh/metabase/<dashboard>/);绝不要使用 /tmp。
阶段 1:设计 — 定义 → 模型图 → 批准
每个阶段都必须获得明确批准;绝不要默默跳过任何阶段。
阶段 1:需求。 业务问题、受众(高管:指标卡片和趋势;分析师:表格和下钻)、数据(databases、tables --database <id>)。然后定义并 提交审批:
| 指标 | 计算方式 | 显示形式 | 卡片 |
|---|---|---|---|
| 总收入 | SUM(total) | 单值 | 收入 KPI |
| 维度 | 来源 | 用途 |
|---|---|---|
| 月份 | orders.created_at (month) | 收入趋势 |
| 筛选器 | 类型 | 默认值 | 应用于 |
|---|---|---|---|
| 日期 | date/all-options | past30days~ | 所有卡片 |
在用户确认前不要继续——数据模型错了,基于它构建的一切都会出错。
阶段 2:渐进式模型图(逐级审批):
- 文本模型图(
assets/templates/mockup-text-template.md)→<project>/design/mockup.md:在 24 列网格上排列指标卡片、图表和表格。 - HTML 模型图(
assets/templates/mockup-html-template.html)→<project>/design/mockup.html,供浏览器查看。 - Metabase 模型图:使用简单的示例 SQL 编写项目(
SELECT 'Gadgets' AS "Category", 42000 AS "Revenue",或使用带LIMIT的真实查询),执行project push,然后运行project render <dir>并向用户展示 PNG——他们无需在 Metabase 中逐个点击,就能看到真实布局、筛选器和格式。
阶段 3:设计文档(assets/templates/design-doc.md)→ <project>/design/design-doc.md。
阶段 2:项目文件
project new <dir> --name "Store Analytics" --database 3 --collection 17
然后编写(格式:specs/project-format.md):
snippets/<name>.sql— 每个数据源对应一个供其他查询使用的片段:包含联接、筛选器([[AND {{date}}]])和时间分组(Postgres/Redshift 使用{{time_perspective}} :: DATE AS period;SQLite 使用DATE({{time_perspective}}))。卡片通过以下方式引用它:WITH base AS ({{snippet: name}}) SELECT …。绝不要在 SQL 注释中放入{{…}}(Metabase 会展开它们)。filters.yaml— 定义片段使用的模板标签:字段筛选器(type: dimension、dimension: [field, {base-type: type/Date}, <field id>]、alias: table_alias.column、widget-type)以及temporal-unit标签。共享标签只需在此定义一次;示例见specs/project-format.md。cards/<key>.sql+cards/<key>.yaml— 每张卡片各一份。SQL 遵循specs/sql-style-guide.md;.yaml 包含名称、描述、显示方式和图表设置。图表卡片必须设置graph.dimensions、graph.metrics(日期还需设置graph.x_axis.scale: timeseries)——参见visualization-cookbook.md顶部的表格。dashboard.yaml— 筛选器(parameters)、标签页、使用at: [col, row, width, height]的布局、每个图块的viz覆盖项,以及筛选器连线:每张带有该标签的卡片都要设置filters: {p_date: date}。
SQL 与 MBQL:对于需要审查、版本管理或复用的内容(CTE、窗口函数、自定义日期逻辑、片段),优先使用原生 SQL;简单聚合和可复用指标则使用 MBQL。结构化问题也适用于项目(其 query: 会保持原样)。
参数化 SQL — 两种不同机制:
- 基本变量(
text、number、date):纯文本替换,运算符由你编写 —WHERE status = {{status}},可选形式为[[AND category = {{category}}]]。 - 字段筛选器(
dimension):由 Metabase 编写条件 —WHERE {{date_range}} [[AND {{category}}]]。绝不要使用WHERE col = {{tag}}(预检会拒绝)。使用表别名时,alias必须采用alias.column格式。
阶段 3:检查、发布、查看
project validate <dir> # must be clean
project lint <dir> # fix, or record deliberate choices under lint.ignore in project.yaml
project test <dir> # every card runs with the default filters, and chart settings are checked
# against the columns each query really returns — must be all ok
project diff <dir> # show the user what will be created
project push <dir> # after the user approves
project lint <dir> # again: column-based rules (number formats, …) only run once cards exist in Metabase
然后运行 视觉检查(见下文)——这是必需步骤。即使设置有误,Metabase 也可能绘制出看似合理的图表(它会回退到另一列),因此图表看起来不错也不能替代干净通过的 project test。
第 4 阶段:测试并交接
project test <dir> --images— 每张卡片都已运行;<dir>/.mbsync/render/中会为每张卡片和每个标签页生成 PNG。- 抽查 2–3 个关键数值,与已知值或直接运行 SQL 的结果对照。
- 筛选器:使用其他值渲染(
dashboard render <id> --params '{"category": "Gizmo"}'),并确认卡片内容发生变化。 - 边界情况:空结果、空值、空筛选器。
- 使用
project render <dir> --pdf交接,让用户无需打开 Metabase 就能查看最终结果,并提交项目文件夹。
视觉检查(每次修改卡片或布局后)
Metabase 会轻松保存错误的图表。请实际查看:
- 创建或修改卡片后: 如果卡片位于仪表板上,使用
dashcard image <dashboard-id> <tile title>(查看者看到的内容:卡片自身的标题、显示值和格式,以及仪表板的默认筛选器——同一张卡片放置了三次,就需要检查三次);如果是独立问题,使用card image <id>。读取 PNG,并检查:- 图表类型是否符合问题;坐标轴是否使用了预期列
- 标签是否清晰易读且没有重叠;排序是否合理
- 数字格式(货币、%、小数位——不能出现
44,383.9);颜色是否与仪表板一致 - 内容不为空且没有错误(JSON 的
error字段);标题和描述是否存在
- 修复并重新渲染——每张卡片最多 3 轮。之后,向用户展示图片并征求意见。
- **每次修改布局后:**运行
dashboard render <id>(或project render <dir>)→ 读取每个标签页的 PNG。检查:- 行是否填满 24 列;KPI 卡片是否对齐且一目了然
- 标题是否区分了各个部分;图表是否拥挤
- 筛选栏是否包含所有筛选器;阅读顺序是否合理
- 每个标签页的 JSON 中
card_errors是否为空
- 交接时附上
--pdf渲染结果。
渲染展示的是 Metabase 当前的内容——先推送项目编辑内容。
STUDY 工作流
在声称自己了解某个仪表板之前,先执行此工作流。只读取 JSON 往往会误述那些以不同设置重复放置多次卡片的仪表板。
- 概览 —
dashboard <id>:collection_authority_level(official= 精选)、card_count与unique_card_count的对比、repeated_card_ids、每个放置位置的overrides(标题、scalar_field、graph_metrics 等)。 - 查看仪表板 —
dashboard render <id>→ 读取每个标签页的 PNG。这可以替代索要截图;只有渲染失败时才需要截图。card_errors会列出出错的卡片。 - 每张唯一卡片 —
card <id>(结果列、片段、模板标签);只有 SQL 才使用--full --out。 - 每个重复放置位置 — 使用
dashcard <dashboard-id> <index|name>查看完整设置。 - 共享片段 — 为每个引用的片段运行
snippet <id>。 - 生成列与显示列 — 将
result_columns与每个放置位置的scalar_field/graph_metrics对照。 - 参数 — 类型、默认值,以及每个参数映射到哪些标签/字段。
- 数据形态 — 对最复杂的卡片运行
card query <id> [--out <file>]。
(如果仪表板是项目文件夹,运行 project pull,然后阅读 dashboard.yaml,即可完成第 1、4 和 7 步。)
EDIT 工作流
以项目文件夹形式管理的仪表板
project pull <dir> # bring in anything changed in Metabase (refuses to overwrite local edits)
# edit the YAML / SQL
project validate <dir> && project lint <dir>
project test <dir> --card <key> # the cards you touched
project diff <dir> # show the user
project push <dir> # then the visual check
- 文件是唯一可信来源。 如果有人在 Metabase 界面中修改了内容,运行
project pull并提交(也包括 ids.json:它记录了每个项目的同步时间,漂移检查会以此为准)。 - 如果 push 报告漂移(“自上次同步这些文件后,Metabase 中的内容已更改”),请停止并询问:保留 Metabase 中的更改(先在其他位置保存编辑内容,再运行
pull --force),还是覆盖这些更改(运行push --yes)。 - 若要停止管理某张卡片但不将其归档,请将其从
cards/以及ids.json中移除。
未作为文件保存的仪表板
- 先 STUDY——它能发现每个放置位置的覆盖设置,避免你不小心将其覆盖。
- 实时卡片才是事实来源,而不是仓库中的任何
.sql文件:从card <id> --full --out开始。 - 布局:对单个放置位置使用
dashcard update <dash> <index|name> --patch f.json;进行较大改动时,使用dashboard <id> --layout --out f.json,编辑后执行dashboard put <id> --from f.json。 - 卡片查询/设置:
card update <id> --patch f.json(保存前会检查)。 - 进行视觉检查。
- 提议将其转为项目:
project pull <dir> --dashboard <id>(在 Metabase 中不执行任何操作;会生成文件、差异 和 git 历史)。
不要读取仓库旧的构建/部署脚本来“了解各部分如何配合”——CLI 已足够。只有在实时数据中看不到某项约定时(例如字段 ID 注册表),或用户要求修改这些脚本时,才读取它们。
分享与定时安排
- 为他人生成图片或 PDF:
dashboard render <id> --server --out <dir>/name.pdf(Metabase 自带的打印 布局,A4/letter,会列出启用的筛选器——最适合分享),dashboard render <id> --out name.pdf(实时 UI 截图,每个标签页一页)或card image <id> --out name.png。筛选器值:--params(仪表板:筛选器 slug;卡片:标签名称)。 - 警报(单张卡片,满足某个条件时触发):按照
specs/notifications-api-spec.md编写请求正文,确认收件人,然后 执行alert create --from f.json。goal_above/below需要卡片上有目标线;否则,应调整卡片,使has_result能表达该条件。在仅将自己设为收件人的情况下进行演练,然后再执行alert send。 - 订阅(按计划发送仪表板):
subscription create --from f.json;省略cards即包含所有 卡片。在项目中,将其放在dashboard.yaml的subscriptions:下,然后推送。 - 如果电子邮件/Slack 未配置,两者都会发出警告——告知用户需要由管理员完成设置;不要创建会悄无声息地无处送达的投递。报告计划时区时,使用实例的报告时区(创建时会打印)。
历史记录
card history <id> / dashboard history <id> 会列出修订记录(操作者、时间、内容)。先与用户确认目标,然后执行
card revert <id> --to <revision-id>。如果是项目文件夹,之后执行 project pull。
探索工作流
databases→tables --database <id>→collections --tree(★ = 官方)→collection-items <id>→search <query>→card <id>/dashboard <id>。- 官方集合(
authority_level: "official")会显示奖章徽标;将集合提升为官方级别需要 Pro/Enterprise。
快捷方式:意图明确时(“按地区显示第三季度销售额”),跳过发现步骤,直接使用 SQL。
使用分析工作流(Pro/Enterprise)
采用情况、陈旧内容、查询性能、使用情况。免费版会在早期阶段拒绝此操作。
usage-analytics— 模型及其卡片 ID(ID 因实例而异;切勿硬编码)。- 如果 8 个内置分析仪表板中有一个能回答问题,优先使用它。
- 否则使用 MBQL(审计数据库会阻止原生 SQL):将查询写入文件,
执行
usage-analytics query --from <file>;浏览时使用:usage-analytics query --card <id> --limit N。
规则:始终按日期筛选 View/Query/Activity 日志(7–30 天);query_source 用于区分人工操作(dashboard、ad-hoc、
question、collection)和自动操作(pulse、dashboard-subscription、cache-refresh);使用 Content 模型的
question_is_native 统计 SQL 与 MBQL 的数量;“External User” = 嵌入式视图。
防护措施
- 每条 SQL 查询都必须聚合或使用 LIMIT。 不要在大型表上执行不受限制的
SELECT *。查询耗时超过 2 分钟,通常意味着排序键缺少日期筛选、预聚合或物化视图。 - 发布前测试 SQL(
project test、card query,或项目使用的数据库技能)。 - 删除即归档。
card delete/dashboard delete会归档(使用restore恢复);只有用户要求彻底删除时,才使用--permanent --yes。集合和代码片段只能归档。 - 预检有其用处。 修复预检报告的问题;只有确定检查有误时才使用
--skip-validate,并说明原因。 - 交付内容会发送给真实的人。 创建提醒/订阅或运行
alert send前,请确认收件人。
常见注意事项
Metabase v63 负载(已在 v0.63.18 上验证):
- 模板标签返回为数组(
[{name: …}]),即使它们是以映射形式编写的;读取时应兼容两种形式。 - 存储的字段引用带有随机的
lib/uuid标记,结构化查询每次读取时也会生成新的lib/uuid—— 这不是变更。(项目 diff/pull 已忽略这些标记。) - 原生卡片的
parameters始终为[];仅对静态列表下拉菜单进行设置。 - v63 中的 Sample Database 使用 SQLite(此前使用 H2):不支持
DATE_TRUNC,应使用strftime('%Y-%m-01', col);通过databases检查数据库引擎。Metabase 会将此类月份列识别为数字;将其保留在graph.dimensions中,并设置graph.x_axis.scale: timeseries。
项目(配置即代码):
- 每次拉取和推送都要提交
ids.json:其中的updated_at值可防止队友推送时覆盖在 Metabase 界面中所做的更改。没有记录时间戳的文件夹会导致推送对每个项目都发出警告。 - 每个代码片段只能有一个所有者。 如果两个项目中的卡片使用同一个代码片段,两个项目的拉取都会写入该片段,最后推送的项目会覆盖前者。请将它保留在一个项目中,并在其他项目的
external_snippets下列出。 - 每个集合只能在一个项目中使用
--loose-cards,切勿在两个项目中使用。 - 切勿将个人集合拉取到共享仓库中。
- 对于要作为文件编辑的内容,优先使用带代码片段的原生 SQL 卡片;结构化(MBQL)问题虽可精确往返转换,但不便手动编辑。
Dashboard PUT 和布局:
tabs必须与dashcards一并提供;每个 dashcard 都必须有card_id(虚拟卡片使用null);负 ID 会创建新标签页/布局项;未提供的布局项会被删除。- 重新创建布局时,布局项 ID 会发生变化,而订阅会引用这些 ID。
project push会复用现有 ID;手动编写的布局也应如此(先获取最新状态)。 - 24 列网格:全宽为
size_x: 24;确保col + size_x ≤ 24;Metabase 会按发送内容存储重叠布局。 - 布局项的
visualization_settings仅对该布局项生效,并覆盖卡片设置;布局项上的column_settings会替换卡片的整个column_settings。
Dashboard 摘要解读:
card_count统计布局项数量;unique_card_count统计不同卡片的数量;repeated_card_ids列出多次放置的卡片——这些卡片几乎总是具有不同的标题/指标。在描述 Dashboard 前,先对每张卡片运行dashcard。overrides是精选的子集(title、scalar_field、graph_metrics、graph_dimensions、series_titles)。对于组合可视化,设置位于visualization.settings下,并使用COLUMN_N名称;摘要会解析这些设置。 筛选器连线:- 筛选器只在完成映射的位置生效。原生 SQL 卡片必须先定义模板标签,映射才能生效。
- 目标:字段筛选器/时间分组使用
["dimension", ["template-tag", t], {"stage-number": 0}];普通变量必须恰好使用["variable", ["template-tag", t]](不接受第三项);文本卡片使用["text-tag", t]。 - 映射中的字段引用需要
{"base-type": "type/Text"}这类选项,不能为null。 - 仅在代码片段中使用的标签,仍必须在每张使用该代码片段的卡片上声明(项目会为你处理);嵌套代码片段中的所有标签都必须在卡片上声明为代码片段标签。
- 字段筛选器不能指向派生列(CASE、计算得出的分桶)——请改用带有静态列表仪表板筛选器的基本
text变量。 - 相对日期默认值:
past7days不包含今天;past7days~包含今天。 - 静态列表的
string/=筛选器需要"values_query_type": "list"才会显示为下拉菜单。 - 文本卡片可以显示筛选器值:在文本中使用
{{d}},并添加目标为["text-tag", "d"]、card_id: null的映射。
显示类型:
pivot仅适用于结构化查询;原生 SQL 应使用display: "table"+"table.pivot": true、table.pivot_column、table.cell_column。使用pivot build构建数据透视表(绝不要手写 MBQL);对数据透视表卡片执行card query会返回用户看到的网格,导出内容默认也会透视(行数据请使用--flat)。详情请参阅食谱“Pivot Table”。- 绝不要创建
visualization_settings: {}的图表卡片——请设置graph.dimensions、graph.metrics,并为日期设置graph.x_axis.scale: timeseries。标量和表格可以从空设置开始。 - 标题:纯文本;文本卡片:Markdown。标题示例:
{"dashcard.background": false, "virtual_card": {"name": null, "display": "heading", "visualization_settings": {}, "archived": false}, "text": "Section"}。
SQL:
- 原生卡片只能使用 pMBQL:
{"lib/type": "mbql/query", "database": <id>, "stages": [{"lib/type": "mbql.stage/native", "native": "<SQL>", "template-tags": {...}}]}——旧格式会静默丢弃数据库。 - 从
dataset_query.stages[0].native读取 SQL,从stages[0].template-tags读取标签。 - 列别名应易于理解并加引号:
AS "Revenue"。从一开始就遵循specs/sql-style-guide.md。 - 绝不要在 SQL 注释中写
{{snippet: x}}——Metabase 也会在注释中展开它。
登录和版本:
- 浏览器登录需要 v63+,以及位于 Admin > AI > MCP 中的应用注册开关。
- Chrome 渲染需要 Chrome 和 Node 22+;
--serverPDF 两者都不需要。两种方式都会显示 Metabase 当前的内容。v63 不支持在服务器端生成单张卡片的 PNG(下载菜单中的 PNG 由浏览器绘制)。 - 免费版会拒绝仅限 Pro/Enterprise 的命令,并显示清晰的提示(可尝试使用
--skip-preflight)。
CLI:--patch/--from 只能接受文件路径。批量更新:先写入所有补丁文件,再循环处理。
示例提示词
“为我构建一个商店业绩仪表板:以每周安装量、转化率和评分为 KPI,包含趋势线、按国家/地区细分,以及日期和国家/地区筛选器。”
NEW → design(指标/维度/筛选器 → 文本 → HTML 模拟图)→ project new → 代码片段、filters.yaml、卡片、dashboard.yaml
→ validate / lint / test → diff → push → 视觉检查(卡片图片、仪表板渲染)→ test --images → 交付 PDF。
“让我看看仪表板 134 的样子——有没有哪里坏了?”
STUDY 第 2 步:dashboard render 134 → 阅读每个标签页 → 报告布局和 card_errors。
“仪表板 22 上的日期筛选器没有影响 Revenue by State 卡片。”
有项目文件夹吗?project pull,检查该卡片位置的 filters: 和卡片的标签,修复、diff、push、render。
否则,运行 dashcard 22 "Revenue by State";如果卡片缺少标签,就添加标签(card update),再用 dashcard update 关联,然后运行 dashboard render 22 --params '{"date": "past30days~"}' 进行确认。
“给我一份商店仪表板的 PDF。” —
dashboard render 134 --out <dir>/store-analytics.pdf。
“每周一 8 点把高管仪表板发给领导团队列表。” — 确认邮箱地址 → 订阅(每周、 周一、8 点)→ 报告时区。在项目中:将其添加到
subscriptions:下并 push。
“如果昨天的注册量低于 50,就提醒我。” — 设置一张仅在注册量 < 50 时返回行的卡片 → 使用
has_result设置提醒,并设为每日 cron。
“上周谁改了卡片 402?把它还原。” —
card history 402→ 确认修订版本 →card revert。
“整理一下 Commercial 集合。” — REORGANIZE:运行
collections --tree、collection-items,提出一种结构, 然后运行collection create,并通过card update/dashboard update配合collection_id移动项目。
“我登录了吗?当前是什么版本?” —
status。