Power BI has no single CLI. Three tools cover the CI, authoring, and comparison roles.

ToolRoleDistributed as
Tabular Editor CLIBPA validation, TMDL manipulation, XMLA deploysWindows .exe, cross-platform via .NET
ALM Toolkit CLIModel diff, selective deploymentWindows .exe; partial CLI
fabric-cicdDeploy PBIP artifacts to Fabric workspacesPython package

Tabular Editor CLI

Tabular Editor 3 ships a command-line mode that runs scripts, BPA rules, and XMLA operations. The binary is called TabularEditor.exe on Windows; a .NET build runs on Linux and macOS.

Run BPA rules

./TabularEditor.exe `
  ./sales_model.SemanticModel `
  -A "./BPA Rules.json" `
  -V

Exit code is 0 on success, non-zero on BPA failures or model errors. Use in CI as a gate.

Run a script

./TabularEditor.exe `
  ./sales_model.SemanticModel `
  -S "./scripts/add_yoy_measures.csx"

Scripts are the idiomatic way to make structural changes to a shared semantic model:

// add_yoy_measures.csx
foreach (var m in Model.AllMeasures.Where(m => m.Name.StartsWith("Total "))) {
    var yoy = m.Table.AddMeasure(m.Name.Replace("Total ", "") + " YoY");
    yoy.Expression = $@"
        VAR Current = [{m.Name}]
        VAR Prior   = CALCULATE([{m.Name}], SAMEPERIODLASTYEAR('dim_date'[date]))
        RETURN DIVIDE(Current - Prior, Prior)
    ";
    yoy.FormatString = "0.00%;-0.00%;0%";
}

XMLA deploy

./TabularEditor.exe `
  ./sales_model.SemanticModel `
  -D "powerbi://api.powerbi.com/v1.0/myorg/workspace-dev" "sales_model" `
  -O "Preserve=false"

Prefer fabric-cicd for routine deploys; reach for Tabular Editor's -D for one-off surgical deploys.

Help

./TabularEditor.exe -h

Full option list. Read it once; come back when you need a flag.

fabric-cicd

Microsoft-published Python package for deploying PBIP artifacts to Fabric workspaces.

Install

pip install fabric-cicd

Validate

fabric-cicd validate --config config.yml

Checks that the PBIP folder structure is correct, workspace IDs in config exist, and environment parameters substitute cleanly.

Deploy

fabric-cicd deploy --target dev --config config.yml
fabric-cicd deploy --target staging --config config.yml
fabric-cicd deploy --target prod --config config.yml

Deploys semantic models and reports to the named target's workspace. Auth via the Azure CLI's active context (typically OIDC from CI).

Config

The config defines workspaces, items (models, reports), and per-target parameters:

workspaces:
  dev:     { id: "00000000-0000-0000-0000-000000000001" }
  staging: { id: "00000000-0000-0000-0000-000000000002" }
  prod:    { id: "00000000-0000-0000-0000-000000000003" }

items:
  - name: sales_model
    type: SemanticModel
    path: ./sales_model.SemanticModel
  - name: sales_report
    type: Report
    path: ./sales_report.Report

environment_parameters:
  dev:
    - name: warehouse_id
      value: "abc123"
  prod:
    - name: warehouse_id
      value: "ghi789"

See the CI/CD guide for the full pipeline.

ALM Toolkit CLI

Compares two tabular models, generates selective deployment scripts.

Compare two models

./AlmToolkit.exe compare `
  --source "Data Source=powerbi://api.powerbi.com/v1.0/myorg/staging;Initial Catalog=sales_model" `
  --target "Data Source=powerbi://api.powerbi.com/v1.0/myorg/prod;Initial Catalog=sales_model" `
  --output diff.txt

Produces a diff of every object (tables, measures, relationships, roles) between source and target.

Selective deploy

./AlmToolkit.exe deploy `
  --source ... --target ... `
  --select "measure:Total Revenue"

Deploys only the named object, preserving the rest.

Use for surgical prod fixes: a single measure definition needs to change, you do not want a full model redeploy, and you do not want to lose parallel PRs that have been merged since the last deploy.

Warning

ALM Toolkit's selective deploy is a surgical tool. Use it for measures and calculated expressions. Avoid it for structural changes (relationships, new tables) where the side effects are larger and a full fabric-cicd deploy is safer.

Power BI REST API via curl

When you need a thing neither tool exposes, hit the REST API directly.

Auth: get a bearer token

TOKEN=$(curl -s -X POST \
  "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \
  -d "grant_type=client_credentials" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET" \
  -d "scope=https://analysis.windows.net/powerbi/api/.default" \
  | jq -r '.access_token')

List workspaces

curl -s "https://api.powerbi.com/v1.0/myorg/groups" \
  -H "Authorization: Bearer $TOKEN" | jq '.value[] | {id, name}'

List datasets in a workspace

curl -s "https://api.powerbi.com/v1.0/myorg/groups/$WORKSPACE_ID/datasets" \
  -H "Authorization: Bearer $TOKEN" | jq '.value[] | {id, name, configuredBy}'

Trigger refresh

curl -s -X POST \
  "https://api.powerbi.com/v1.0/myorg/groups/$WORKSPACE_ID/datasets/$DATASET_ID/refreshes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type": "full", "commitMode": "transactional"}'

Refresh history

curl -s "https://api.powerbi.com/v1.0/myorg/groups/$WORKSPACE_ID/datasets/$DATASET_ID/refreshes" \
  -H "Authorization: Bearer $TOKEN" | jq '.value[] | {status, startTime, endTime}'

When to use which tool

TaskTool
CI deploy of PBIP to a workspacefabric-cicd
BPA validation in CITabular Editor CLI
Scripted model edits (bulk add, refactor)Tabular Editor CLI
Compare two models, see what differsALM Toolkit CLI
Deploy one measure without redeploying everythingALM Toolkit CLI
Trigger a refresh, query refresh historyREST API (curl/Python)
List/enumerate workspaces, datasetsREST API

See also