A CLI for querying Metabase databases.
curl -fsSL https://raw.githubusercontent.com/carlosarraes/mb-cli/main/install.sh | shTo install a specific version:
curl -fsSL https://raw.githubusercontent.com/carlosarraes/mb-cli/main/install.sh | MB_VERSION=v0.1.0 shIn PowerShell:
irm https://raw.githubusercontent.com/carlosarraes/mb-cli/main/install.ps1 | iexTo install a specific version:
$env:MB_VERSION='v0.1.0'; irm https://raw.githubusercontent.com/carlosarraes/mb-cli/main/install.ps1 | iexInstalls mb.exe to %LOCALAPPDATA%\Programs\mb and adds it to your user PATH.
You can run mb immediately in the same terminal — no restart needed.
Pre-built binaries for Linux, macOS, and Windows are available on the Releases page.
just buildRequires Rust and just.
Builds and copies mb to ~/.local/bin/.
mb configPrompts for Metabase URL and auth (API key or session token from browser cookie).
| Command | Description |
|---|---|
mb config |
Set Metabase URL and authentication |
mb databases |
List all databases |
mb tables <db> |
List tables in a database |
mb fields <db> <table> |
List fields with types |
mb query <db> "SQL" |
Run a native SQL query (also --file q.sql or piped stdin) |
mb collections |
List collections |
mb collection <id|name> |
List the contents of a collection |
mb questions |
List saved questions (cards) |
mb question <id|name> |
Inspect a saved question |
mb search <pattern> |
Search the SQL text of every saved question |
mb dashboards |
List dashboards |
mb dashboard <id|name> |
Inspect a dashboard, or add cards and tabs to it |
mb new dashboard |
Create a dashboard |
mb new question |
Create a native SQL question |
mb skill add |
Install the AI agent skill and link to detected agents |
mb skill update |
Update skill to the latest version |
mb skill remove |
Remove skill and unlink from all agents |
mb skill status |
Show installation and version info |
Database and table args accept name or ID.
The skill command manages an AI agent skill that teaches Claude, Cursor, and Codex how to use mb effectively. It downloads the skill files and symlinks them into each detected agent's skill directory.
mb databases
mb tables analytics
mb fields analytics users
mb query analytics "SELECT * FROM users LIMIT 10"
mb query analytics "SELECT * FROM users" --json
mb query analytics "SELECT * FROM users" --csv
# SQL from a file or stdin — avoids shell quoting entirely
mb query analytics --file report.sql
mb query analytics < report.sql
cat report.sql | mb query analytics --csv
# Collections and saved questions
mb collections
mb collection 400
mb collection "Finance" --model dashboard
mb questions --search "monthly report"
mb question 4707 --sqlFind every question whose SQL touches a table:
mb search orders_invoice # substring, with grep -n style locations
mb search '\borders_invoice\b' --regex # exact name, excludes orders_invoiceitem
mb search orders_invoice --ids # bare card IDs for scripting1082 Infos do signatário e do documento pelo SIGNER TOKEN
14: JOIN orders_invoice oi
The default engine downloads every card once, caches it for an hour, and matches
locally — so the first search takes ~30s and the rest are instant. --fast uses
Metabase's search index instead: about ten times quicker, but it matches tokens
rather than literal text, misses a real share of SQL references, and cannot report
line numbers. The engine and cache age always print to stderr.
Only native SQL questions are searchable; GUI questions reference tables by numeric ID, and the banner reports how many were skipped.
mb new dashboard --name "Funil" --collection 400
mb new question --name "Docs/dia" --db 2 --sql-file q.sql --collection 400 --if-not-exists
mb dashboard 448 # inspect: tabs, cards, grid positions
mb dashboard 448 --add-card 4598 --size 8x4 # merged into the existing layout
mb dashboard 448 --add-card 4598 --tab "Conversão"
mb dashboard 448 --add-tab "Retenção"
mb question 4598 --run --csv # execute and export
mb question 4598 --usage # which dashboards render it
mb question 4598 --update --sql-file new.sql # diffs and validates first
mb question 4598 --archiveEvery write supports --dry-run, --yes, and --force.
PUT /api/dashboard/:id replaces the whole dashcards array, so --add-card reads the
dashboard, appends, and writes the merged result. You never hand it a layout, which
deletes the "I clobbered a colleague's dashboard" failure mode instead of warning about it.
Writes re-read immediately before writing and compare against what they first read,
scoped to what is actually changing. Adding a card while someone else edits another tab
re-merges and proceeds; overwriting a dashcard they just moved aborts. Concurrent is not
the same as conflicting — a guard that fires on every concurrent edit just teaches people
to type --force.
The comparison uses content, not timestamps, because Metabase does not bump a dashboard's
updated_at when its dashcards change.
--force still reads, compares, and prints who made the change it is discarding.
--dry-run resolves IDs and validates SQL by running it, so it catches real errors.
When stdin is not a terminal, writes require --yes and fail immediately rather than
blocking on a prompt nobody can answer.
mb --llmPrints query guidance and examples optimized for LLM agents.