Fabric CLI
Guidance for using fab to programmatically manage Fabric & Power BI service
- Install via
uv tool install ms-fabric-cli (get uv via winget install uv or brew install uv)
- Fabric CLI is for working with the Cloud environment and not local files; it works with Power BI Pro, PPU, or Fabric; you DO NOT need a Fabric SKU to use the Fabric CLI
- Keep
fab current: check the installed version against the latest ms-fabric-cli release and upgrade with uv tool upgrade ms-fabric-cli unless the user has pinned a specific version. Discover commands and flags with fab --help and fab <command> --help rather than hard-coding behavior; the CLI surface changes regularly
[!IMPORTANT]
When you learn something generic about fab (an error and its real cause, a request shape the
docs get wrong, an undocumented response envelope, a prerequisite that is not written down),
record it where it will still be true for the next reader. Service and API behaviour goes in the
references/*.md file that already owns that topic; the reference map at the end of this file is
the index. Anything that names an operating system, a shell, an installed binary or a fab
version carries its scope in the sentence, per the boundary rule below.
This skill folder is the only copy that ships. A note in a per-agent memory file is per-machine
and per-user, so a second machine, a Codespace, and everyone else running this plugin never see it.
Generic learnings only, never item- or task-specific ones. Do not write a change log. If the fact
is already in the skill, improve the one copy rather than restating it somewhere else.
Where a new learning goes
Three questions, in order. Stop at the first yes.
1. Is it true only because of how THIS machine is set up right now?
An installed path, which identity you are logged in as, a preview toggle, a console codepage, which
build happens to be installed. Then it is machine-local.
Before accepting that answer, try to generalise it. Most machine-local facts are the residue of a
search that succeeded once, and the search is the portable part:
| Instead of recording |
Record |
| the path where you found a DLL |
the probe that finds it, and how to tell which host can load it |
| that a preview toggle is off here |
the verbatim symptom string, and the route that works regardless |
| which account has rights here |
the check that reveals the mismatch |
| that a script cannot find a binary |
a fix to the script |
If the generalised form survives, it is not machine-local: take it to question 2 or 3. If nothing
survives, because the fact is about one machine, one tenant or one person, write it to the agent's
own memory file and nowhere else. It would mislead an agent anywhere else, and this repository is
public.
A Codespace has no legitimate machine-local layer. A fact about a Codespace is true of every
Codespace built from the same devcontainer, which makes it a fact about that image. Commit it.
Never start a memory file inside a container.
2. Is it true only where Power BI Desktop runs, only in a Windows shell, or only at some tool
version?
Then it is portable knowledge with a boundary. It goes in this skill's references/, with the
boundary in the sentence:
- Platform: open or close with the scope. "On a cp1252 Windows console ... Linux and macOS never
hit this." "Power BI Desktop only."
- Version: write the symptom and the check as the instruction, never the version. "If
fab find
errors, run fab --version before assuming a syntax problem." Put the version and date you
observed in brackets at the end, never in the imperative. A version in the imperative rots into a
lie; a version in brackets rots into a footnote.
- A dated or version-pinned claim also carries a
Retest: line naming the one command that settles
it, plus a Verified <date> stamp. scripts/check-skill-hygiene.py reports the stale ones and
fails on a version claim with no Retest:.
A scoped statement that is a ROUTE is not finished until it names the substitute in the same
sentence. "pbir desktop screenshot is Windows and Desktop only" leaves a Linux agent stuck.
"pbir desktop screenshot is Windows and Desktop only; where Desktop is unavailable, render
server-side with the ExportTo API (fabric-cli references/reports.md)" does not.
3. Otherwise it is a fact about the file format, the product, or the service API.
True everywhere, including a Codespace with no Desktop and no Windows. It goes in this skill's
references/ with no qualifier, or in SKILL.md when the agent must know it before opening any
reference. This is the default and where most learnings land.
Two tests that settle almost every case
- Would this sentence still be true in a Linux Codespace with no Power BI Desktop? Yes means
question 3. No, but only because Desktop is missing, means question 2. No, because the sentence
names a path, a version or a toggle, means question 1, so run the generalisation table first.
- Could anyone else running this plugin act on it? If not, question 1.
When torn, file it in the more public place
An over-cautious scope clause on a portable fact costs a reader one clause. A machine-local fact
shipped as product knowledge misleads everyone who installs the plugin.
Where to write it
If PBI_MARKETPLACE_ROOT is set, a writable clone of this marketplace is on the machine:
bash "$PBI_MARKETPLACE_ROOT/scripts/record-learning.sh" writes the note, runs the hygiene scan,
commits to a branch and opens a pull request.
If it is unset, the skills are loading from a read-only plugin cache and an edit there is discarded
by the next plugin update. Write the note to the agent's memory file instead, and say plainly in
the note that it still needs promoting into the plugin.
Nothing portable belongs in ~/.claude/rules/, .cursor/rules/ or .github/instructions/. Those
are per-machine and per-user.
When to use this skill
- Use whenever the user mentions "Fabric" or "Power BI"
- Use when user asks about Power BI workspaces, deployment, tenants, publishing, download, permissions, or data
Critical general rules
- IMPORTANT: The first time you use
fab run check that it is up to date to the latest version (upgrade with uv tool upgrade ms-fabric-cli unless the user has pinned a version) and run fab auth status; If user isn't authenticated, ask them to run fab auth login
- On a Windows console left on the cp1252 codepage,
fab dies part-way through its own output with 'charmap' codec can't encode character even though the server-side work succeeded; export PYTHONIOENCODING=utf-8 and PYTHONUTF8=1 in every shell block that calls fab (details in reference.md). Linux and macOS never hit this
- Always use
fab --help and fab <command> --help the first time you use a command to understand its syntax
- You must search the skill /references/ for relevant reference files that explain certain commands, examples, scripts, or workflows before you start using
fab
- Before first use, ask the user if they have Fabric admin access, sensitivity labels or DLP policies, any API restrictions, or preferences for Fabric/Power BI API usage; remind user to add this to memory files
- If workspace or item name is unclear, ask the user first, then verify with
fab ls or fab exists before proceeding
- Ensure that you avoid removing or moving items, workspaces, or definitions, or changing properties without explicit user direction
- If a command is blocked in your permissions and you try to use it, stop and ask the user for clarification; never try to circumvent it
- Create output directories before export:
fab export does not create intermediate directories; mkdir -p the output path first or the command fails with [InvalidPath]
Use -f (force) for non-interactive use
The fab CLI prompts for confirmation, so you you must always append -f to prevent this UNLESS sensitivity labels are enabled, in which case you must ask the user. Do this for the commands:
fab get -q "definition" ; sensitivity label confirmation
fab export ; sensitivity label confirmation
fab import ; overwrite confirmation
fab cp / fab cp -r ; overwrite and sensitivity label confirmation
fab rm ; delete confirmation
fab assign / fab unassign ; capacity/domain assignment confirmation
fab mv ; rename/move confirmation
Quickstart guide
You must read and understand the common list of operations with simple examples
- Check the commands, syntax, and auth status:
fab --help and fab auth status
- Check if the item exists if the user gave the workspace and item name:
fab exists "spaceparts-dev.Workspace/spaceparts-otc-full.SemanticModel"
- Find an item by name across every workspace the user can see:
fab find 'sales' -P type=Report -l (substring on name, description, workspace; -P type= to filter, -l for ids; -q '<jmespath>' for client-side filter/projection). For governance workflows that need last visit / last refresh / owner / storage mode / capacity SKU, use scripts/search_across_workspaces.py; see workspaces.md for the delta.
- Find the workspace:
fab ls
- Find the item:
fab ls "Workspace Name.Workspace"
- Check the commands for that item:
fab desc to get itemTypes
fab desc .<ItemType> for commands i.e. fab desc .SemanticModel
- What's in that item; what's it for; what is it?:
- Full TMDL definition:
fab get "spaceparts-dev.Workspace/spaceparts-otc-full.SemanticModel" -q "definition" -f
- Search a specific measure / table / column:
fab get "ws.Workspace/Model.SemanticModel" -q "definition" -f | rga -i "Sales Amount"
- Retrieve AI instructions / AI schema:
python3 scripts/get_semantic_model_ai_metadata.py "ws.Workspace/Model.SemanticModel" --instructions-out instructions.md --schema-out schema.json
- Get files, tables, or table schemas:
- List lakehouse files:
fab ls "ws.Workspace/LH.Lakehouse/Files"
- List lakehouse tables:
fab ls "ws.Workspace/LH.Lakehouse/Tables"
- Table schema:
fab table schema "ws.Workspace/LH.Lakehouse/Tables/gold/orders"
- Query data (always prefer the wrapper scripts over raw
fab api / duckdb / sqlcmd; they resolve IDs, hosts, and auth for you):
- Semantic model (DAX):
python3 scripts/execute_dax.py "ws.Workspace/Model.SemanticModel" -q "EVALUATE TOPN(10, 'Orders')"
- Lakehouse SQL endpoint, warehouse, or SQL database (T-SQL): prefer the
fabric-sql MCP execute_query(workspaceId, itemId, query) when it is loaded; fall back to python3 scripts/query_sql_endpoint.py "ws.Workspace/LH.Lakehouse" -q "SELECT TOP 10 * FROM dbo.orders". See querying-data.md
- Lakehouse or warehouse Delta over OneLake (DuckDB):
python3 scripts/query_lakehouse_duckdb.py "ws.Workspace/LH.Lakehouse" -q "SELECT * FROM tbl LIMIT 10" -t gold.orders
- Set properties for an item or workspace:
fab set "ws.Workspace/Item.Notebook" -q displayName -i "New Name" or fab set "ws.Workspace" -q description -i "Production environment"
- Review or manage permissions:
- Item ACL:
fab acl ls "ws.Workspace/Model.SemanticModel" then fab acl set "ws.Workspace/Model.SemanticModel" -I user@contoso.com -R Read
- Workspace roles:
fab acl ls "ws.Workspace" then fab acl set "ws.Workspace" -I user@contoso.com -R Member
- Setting up a service principal for automation instead of a human identity: service-principals.md - creation via az CLI, the workspace-role-plus-tenant-setting-group double requirement, and how to authenticate
fab as it
- Deploy items to Fabric:
fab import "ws.Workspace/New.Notebook" -i ./local-path/Nb.Notebook -f
- Download items from Fabric:
fab export "ws.Workspace/Nb.Notebook" -o ./backup -f (always mkdir -p ./backup first)
- Copy or move items between workspaces:
fab cp "dev.Workspace/Item.Notebook" "prod.Workspace" -f or fab mv "ws.Workspace/Old.Notebook" "ws.Workspace/New.Notebook" -f
- Open item in Fabric via browser:
fab open "spaceparts-dev.SpaceParts/Amazing Report.Report"
- Using Fabric or Power BI APIs:
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}' or fab api "workspaces/<ws-id>/items"
- Using Azure CLI (advanced) when Fabric CLI doesn't suffice:
- T-SQL over any SQL-capable item ; use
scripts/query_sql_endpoint.py (reuses az login via ActiveDirectoryAzCli; full walkthrough in querying-data.md)
- Pass a Key Vault secret to a consumer without ever reading, echoing, or persisting it:
az login --service-principal -u <appId> -t <tenantId> --password "$(az keyvault secret show --vault-name <vault> --name <secret> --query value -o tsv)" ; command substitution pipes the secret directly into the child process arg list, never stdout, a file, or a named shell variable
- Calling
az from a Python script on Windows needs two accommodations that Linux and macOS do not: resolve the executable with shutil.which("az") so PATHEXT is honoured, and pass the command as one string with shell=True under Git Bash ; fab-vs-az-cli.md
- Full fab-vs-az decision matrix: fab-vs-az-cli.md
Essential Concepts
For information about any concepts related to Power BI or Fabric you must search or fetch via the microsoft-learn MCP server (or the pbi-search CLI as an alternative) and ask the user questions with the AskUserQuestion tool; NEVER guess or make assumptions.
Workspaces
- Workspaces are containers for items like Notebooks (and other ETL items), Lakehouses (and other data items), SemanticModels, Reports (and other consumption items), and OrgApps.
- Workspaces can be assigned to different things:
- Deployment Pipelines for lifecycle management (Dev, Test, Prod, etc.)
- Domains for governance and tenant structuring
- Capacities for licensing and resources (Fabric or Premium capacities only; PPU and Pro work differently)
- Git repositories for Source Control via Git integration
Key Patterns
Pay special attention to each of the following areas when using the Fabric CLI
Path Format
Fabric uses filesystem-like paths with type extensions:
"WorkspaceName.Workspace/ItemName.ItemType"
You must quote paths with spaces and punctuation:
"Workspace Name.Workspace/Semantic Model Name.SemanticModel"
For lakehouses this is extended into files and tables:
WorkspaceName.Workspace/LakehouseName.Lakehouse/Files/FileName.extension or /WorkspaceName.Workspace/LakehouseName.Lakehouse/Tables/TableName
For Fabric capacities you have to use fab ls .capacities
Examples:
"Production Workspace.Workspace/Sales Report.Report"
Data.Workspace/MainLH.Lakehouse/Files/data.csv
Data.Workspace/MainLH.Lakehouse/Tables/dbo/customers
Common Item Types
.Workspace - Workspaces
.SemanticModel - Power BI datasets
.Report - Power BI reports
.Notebook - Fabric notebooks
.DataPipeline - Data pipelines
.Lakehouse / .Warehouse/ .SQLDatabase - Data artifacts
.SparkJobDefinition - Spark jobs
.AISkill - Fabric Data Agents
.MirroredDatabase / .MirroredWarehouse - Mirrored databases
.Environment - Spark environments
.UserDataFunction - User data functions
Full list: You must use fab desc or fab desc .<ItemType> to check syntax and types if the user asks about an item type not listed above.
JMESPath Queries
Filter and transform JSON responses with -q:
# Get single field
-q "id"
-q "displayName"
# Get nested field
-q "properties.sqlEndpointProperties"
-q "definition.parts[0]"
# Filter arrays
-q "value[?type=='Lakehouse']"
-q "value[?contains(name, 'prod')]"
# Get first element
-q "value[0]"
-q "definition.parts[?path=='model.tmdl'] | [0]"
Using fab api
fab has an api escape hatch that lets you use any API even if it doesn't have primary commands.
Variable Extraction Pattern
To use fab api you need item IDs. Extract them like this:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')
# Then use in API calls
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'
Admin APIs (Requires Admin Role)
Don't use admin commands or APIs if the user doesn't have Admin access. Here's some examples:
# Find semantic models by name (cross-workspace)
fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name, 'Sales')]"
# Find all notebooks
fab api "admin/items" -P "type=Notebook" -q "itemEntities[].{name:name,workspace:workspaceId}"
# Find all lakehouses
fab api "admin/items" -P "type=Lakehouse"
# Common types: SemanticModel, Report, Notebook, Lakehouse, Warehouse, DataPipeline, Ontology
For full admin API reference (cross-workspace discovery, tenant settings read/update, capacity/domain/workspace overrides, activity events): admin.md
Error Handling & Debugging
# Show response headers
fab api workspaces --show_headers
# Verbose output
fab get "Production.Workspace/Item" -v
# Save responses for debugging (fab api has no -o flag; redirect stdout)
fab api workspaces > /tmp/workspaces.json
Common workflows
These are the most common workflows you'll encounter in Fabric
Finding or exploring workspaces, items, or metadata
| Command |
Purpose |
Example |
fab ls |
List workspaces / items |
fab ls "Sales.Workspace" -l |
fab exists |
Check if a path exists |
fab exists "Sales.Workspace/Model.SemanticModel" |
fab get |
Get item details |
fab get "Sales.Workspace" -q "id" |
fab desc |
Supported commands per type |
fab desc .SemanticModel |
Flags:
-l (long listing)
-a (show hidden items)
-q (JMESPath filter)
-v (verbose output)
-o (save response to file)
Fabric discovery follows a drill-down pattern:
- Browsing:
- List workspaces:
fab ls
- List items in a workspace:
fab ls "ws.Workspace" -l
- Confirm a path exists:
fab exists "ws.Workspace/Item"
- Check what commands an item type supports:
fab desc .<ItemType>
- Inspection:
- Get item details:
fab get "ws.Workspace/Item"
- Pull a single field:
fab get "ws.Workspace" -q "id"
- Cross-workspace search:
Check references before exploring:
Querying data
| Command |
Purpose |
Example |
fab get -q "definition" |
Get model schema |
fab get "ws.Workspace/Model.SemanticModel" -q "definition" -f |
fab api -A powerbi |
Execute DAX |
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE..."}]}' |
fab ls |
Browse files / tables |
fab ls "ws.Workspace/LH.Lakehouse/Files" |
fab table schema |
Lakehouse table schema |
fab table schema "ws.Workspace/LH.Lakehouse/Tables/sales" |
fab cp |
Upload / download OneLake file |
fab cp ./local.csv "ws.Workspace/LH.Lakehouse/Files/" |
duckdb + delta_scan |
Query Delta tables (requires DuckDB) |
duckdb -c "... delta_scan('abfss://<ws-id>@onelake.../<lh-id>/Tables/schema/table')" |
duckdb + read_csv/json |
Query raw files (requires DuckDB) |
duckdb -c "... read_csv('abfss://.../Files/data.csv')" |
Flags:
-A fabric|powerbi|storage|azure (API audience)
-X get|post|put|delete|patch (HTTP method)
-i (JSON body or file)
-f (skip sensitivity prompt on definition pulls).
Fabric exposes three query paths depending on the source; always prefer the wrapper scripts -- they resolve IDs, hosts, and auth for you:
- Semantic models (DAX):
- Find model fields first:
fab get "ws.Workspace/Model.SemanticModel" -q "definition"
- Query:
scripts/execute_dax.py
- Lakehouses / Warehouses via Delta over OneLake (DuckDB):
- Lakehouse SQL endpoint, Warehouse, or SQL Database (T-SQL):
- Prefer the
fabric-sql MCP execute_query(workspaceId, itemId, query) when loaded; server-side, no local tooling
- Fall back to
scripts/query_sql_endpoint.py (sqlcmd; auto-detects host per item type, reuses az login via ActiveDirectoryAzCli) when the MCP is unavailable
- Prefer either over DuckDB when you need
INFORMATION_SCHEMA, sys.* metadata, CTEs, or window functions
- Full route priority: querying-data.md
Check references before writing queries:
Changing metadata or access (descriptions, tags, endorsement, properties, bindings, permissions)
| Command |
Purpose |
Example |
fab set |
Update property |
fab set "ws.Workspace/Item" -q displayName -i "New Name" |
fab mv |
Rename / move item |
fab mv "ws/Old.Notebook" "ws/New.Notebook" -f |
fab acl ls |
List permissions |
fab acl ls "ws.Workspace" |
fab acl set |
Grant permission |
fab acl set "ws.Workspace" -I <objectId> -R Member |
fab acl rm |
Revoke permission |
fab acl rm "ws.Workspace" -I <upn> |
fab label set |
Set sensitivity label |
fab label set "ws/Nb.Notebook" --name Confidential |
Flags:
-q <field> + -i <value> (set a single property)
-I (object ID or UPN for fab acl)
-R Admin|Member|Contributor|Viewer (role for fab acl set)
-f (skip confirmation; ask user first if sensitivity labels are in play)
Metadata and access changes fall into a few groups:
- Properties (displayName, description, sensitivity config):
- Native update:
fab set "<path>" -q <field> -i "<value>"
- Capture current state first so you can revert:
fab get -v -o /tmp/before.json
- Endorsement, certification, and tags (no first-class
fab commands):
- Patch via
fab api with item-specific endpoints
- Tag workflow: tags.md
- Endorsement patterns: reference.md
- Folder placement:
- Move items between workspace subfolders: folders.md
- Access control and sensitivity labels:
- Grant / revoke:
fab acl set, fab acl rm
- Set sensitivity label:
fab label set
- Verify the principal first:
az ad user show
- Never change permissions or labels without explicit user confirmation
- Bindings:
Check references before changing metadata:
Working with workspaces
| Command |
Purpose |
Example |
fab mkdir |
Create workspace / item |
fab mkdir "New.Workspace" -P capacityname=MyCapacity |
fab assign |
Attach capacity / domain |
fab assign .capacities/cap.Capacity -W ws.Workspace -f |
fab unassign |
Detach capacity / domain |
fab unassign .capacities/cap.Capacity -W ws.Workspace |
fab start / fab stop |
Resume / pause capacity |
fab start .capacities/cap.Capacity |
fab cp -r |
Fork workspace |
fab cp "dev.Workspace" "prod.Workspace" -r -f |
fab rm |
Soft-delete (see recovery) |
fab rm "ws/Item.Type" -f |
Flags:
-P key=value (creation params for fab mkdir)
-W (target workspace for fab assign / fab unassign)
-r (recursive copy/move)
-bpc (block on path collision for fab cp)
-f (skip confirmation)
Workspace-scope operations fall into a few groups:
- Create and provision:
- Create workspace:
fab mkdir "<Name>.Workspace" -P capacityname=<cap>
- Attach capacity or domain:
fab assign .capacities/<cap>.Capacity -W <ws>.Workspace
- Planning context, create/get/set surface, large storage format, Spark pools, OneLake defaults, Git: workspaces.md
- Copy, fork, download:
- Duplicate a workspace in-tenant:
fab cp -r "dev.Workspace" "prod.Workspace"
- Dry-run the source tree first:
fab ls "dev.Workspace"
- Full local snapshot (items + lakehouse files):
scripts/download_workspace.py
- Permissions:
- Inspect / grant / revoke:
fab acl ls | set | rm
- Tenant-wide governance audit: use the
audit-tenant-settings skill from the fabric-admin plugin
- Connections and gateways (bound to, but outside, the workspace):
- Credential types (WorkspaceIdentity, SPN, Basic), OAuth2 limits: connections.md
- Datasource binding, credential rotation: gateways.md
- Folders inside a workspace:
Check references before modifying workspaces:
Executing or scheduling jobs (notebooks, notebook cells, pipelines, semantic model refresh)
| Command |
Purpose |
Example |
fab job run |
Run synchronously |
fab job run "ws/ETL.Notebook" -P date:string=2025-01-01 |
fab job start |
Run asynchronously |
fab job start "ws/ETL.Notebook" |
fab job run-list |
List executions |
fab job run-list "ws/Nb.Notebook" |
fab job run-status |
Check status |
fab job run-status "ws/Nb.Notebook" --id <job-id> |
fab job run-cancel |
Cancel a job |
fab job run-cancel "ws/Nb.Notebook" --id <job-id> -w |
scripts/run_notebook_checked.py |
Run a notebook + verify its exit value (status Completed ≠ ETL succeeded) |
python3 scripts/run_notebook_checked.py "ws/ETL.Notebook" |
fab api -A powerbi .../refreshes |
Trigger semantic model refresh |
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}' |
Flags:
-P key:type=value (parameters, type is string|int|bool)
--id (job run ID)
-w (wait on cancel)
--timeout (overall timeout for synchronous runs; it can crash the client poller with '<' not supported between instances of 'int' and 'str' while the job still runs server-side, so do not resubmit, see notebooks.md)
--polling_interval (status poll cadence)
Jobs map to different endpoints depending on item type:
- Notebooks and pipelines:
- Run synchronously:
fab job run "ws/ETL.Notebook" -P date:string=2025-01-01
- Run asynchronously:
fab job start "ws/ETL.Notebook"
- Check status:
fab job run-status "ws/Nb.Notebook" --id <job-id>
- List history:
fab job run-list "ws/Nb.Notebook"
- Verify the REAL outcome: a job
Completed only means the process finished -- a notebook can catch its own exception and exit a failure payload while still showing Completed. Read its exit value, or use scripts/run_notebook_checked.py; details in notebooks.md
- Python / PySpark kernels, Livy sessions, cell-level CRUD: notebooks.md
- Semantic model refresh (not exposed as
fab job):
- Trigger:
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}'
- Check current run before starting a new one (409 if already running):
fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes?\$top=1"
- Enhanced refresh, incremental policies, partition targeting: semantic-models.md
- Dataflow refresh:
- Scheduling:
Check references before running jobs:
Fabric admin operations (auditing, management)
| Command |
Purpose |
Example |
fab api "admin/items" |
Cross-workspace item search |
fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name,'Sales')]" |
fab api "admin/workspaces" |
Workspace inventory |
fab api "admin/workspaces" |
fab api "admin/tenantsettings" |
Tenant settings |
fab api "admin/tenantsettings" |
fab api "admin/capacities" |
Capacity inventory |
fab api "admin/capacities" |
fab api -X post .../update |
Update tenant setting |
fab api -X post "admin/tenantsettings/<name>/update" -i body.json |
Flags:
-P key=value (query params, e.g. type=SemanticModel)
-q (JMESPath filter)
-X post + -i (write ops)
--show_headers (inspect Retry-After on 429)
Admin-scope work is gated behind the Fabric / Power BI admin role. Confirm access first with fab api "admin/capacities" 2>&1 | head -5; if it errors, stop rather than retry.
Two entry points cover most admin tasks:
- Governance audits (tenant settings, delegated overrides, Entra SG scoping):
- Use the
audit-tenant-settings skill from the fabric-admin plugin. It owns the curated metadata baseline, the audit + change-detection script, delegated-override enumeration, and the Entra SG investigation workflow.
- Invoke it whenever the question combines tenant posture with group membership, override scope, or drift against the baseline.
- Raw admin APIs (cross-workspace search, activity events, artifact access, item search):
- Patterns in admin.md
- Rate limit: 25 write requests / minute; honor
Retry-After on 429
- Print the exact command and wait for user confirmation before any destructive admin operation
Check references before admin work:
Definitions and deployment (item definitions, deployment pipelines, git integration, cicd)
| Command |
Purpose |
Example |
fab get -q "definition" |
Read raw definition |
fab get "ws/Model.SemanticModel" -q "definition" -f |
fab export |
Export item to local |
fab export "ws/Nb.Notebook" -o ./backup -f |
fab import |
Import item from local |
fab import "ws/Nb.Notebook" -i ./backup/Nb.Notebook -f |
fab cp |
Copy between workspaces |
fab cp "dev/Item" "prod.Workspace" -f |
fab api "deploymentPipelines" |
Deployment pipelines API |
fab api "deploymentPipelines" -q "value[]" |
Flags:
-o (output path for fab export)
-i (input path or JSON body for fab import)
--format (definition format for export / import)
-f (skip overwrite and sensitivity prompts)
[!IMPORTANT]
The poll interval is by far the biggest performance lever for any definition change.
Creating or updating an item definition is a long-running operation (LRO): the API returns
202 Accepted with a Retry-After: 20 header. fab import, nb create, and nb cell edit
wait roughly that long between status polls, so a notebook that the server finishes in ~1s
takes them 25-60s. Neither fab nor nb exposes a knob to change that interval.
For notebook definition changes, strongly prefer scripts/deploy_notebook.py,
which polls the LRO every ~0.3s (tunable via --poll-interval) and creates in ~1-2s or updates
in place in ~1s. Auto-detects create vs update. When you must roll your own for another item
type, the rule is the same: poll updateDefinition / create at ~0.3s, not the advertised 20s.
python3 scripts/deploy_notebook.py "ws.Workspace/ETL.Notebook" -i ./ETL.Notebook # create or update in place
Every Fabric item has a serializable definition. Move definitions between environments depending on scope:
- Single item:
- Round-trip locally:
fab export then fab import (always mkdir -p the output directory first; fab export does not create intermediate directories and fails with [InvalidPath])
- For a
.SemanticModel there is a second caveat: fab export omits definition.pbism and fab import requires it, so write {"version":"4.2","settings":{}} to the item root before importing or the import fails with Workload_FailedToParseFile ... Required artifact is missing in 'definition.pbism'; see import-download-deploy.md
- Same-tenant shortcut, no local hop:
fab cp "dev/Item" "prod.Workspace"
- Semantic model as PBIP (TMDL + blank report):
- Export the model with
fab export, create the report with pbir new report, then combine
them with pbir report merge-to-thick; see import-download-deploy.md
- Full workspace snapshot (items + lakehouse files):
- Promotion between Dev, Test, Prod:
- Fabric deployment pipelines API (covers all item types)
- Power BI pipelines API (Power BI items only, but finer-grained deploy flags like
allowPurgeData, allowTakeOver)
- When to use each, selective deploy, LRO polling: deployment-pipelines.md
- Git integration (connect workspace to repo, branch, commit, update from git):
Check references before deploying:
Related skills
audit-tenant-settings (in the fabric-admin plugin) ; Fabric governance workflow covering tenant settings, delegated overrides (capacity / domain / workspace), and the Entra security groups those settings reference. Read-only; holds the curated metadata baseline and the audit + change-detection script.
Gotchas
- IMPORTANT: DON'T try to use
fab ls on items that aren't data items (.Lakehouse, .Warehouse, etc); use fab ls to find workspaces and items, and use fab get to look at definitions
- ALWAYS Use the
-f flag when using fab get, fab import, fab export, etc. as described above
- ONLY fallback to
fab api when a command doesn't exist
fab api returns a {status_code, text} envelope, not the raw body: -q filters must start with text. or they silently return None, there is no -o flag (redirect stdout), and binary bodies (PDF, PNG, XLSX, PBIX, .rdl) are corrupted, so fetch files over raw HTTP with an az bearer token. See fab-api.md
- Definition changes feel slow but aren't:
fab import / nb create / nb cell edit take 25-60s to push a notebook definition only because they poll the LRO at the server's Retry-After: 20. The work is ~1s. Use scripts/deploy_notebook.py (tight-polls at ~0.3s) for definition changes; the poll interval is the single biggest lever
References
Reference map (which references cluster together; follow the links between them, not just this list):
etl / notebooks
notebooks.md ── run jobs, exit value, scheduling
├─ querying-data.md ── nb exec / Livy, DuckDB/sqlcmd, SQL-endpoint sync
└─ lakehouses.md ── attach, table ops, OneLake shortcuts, SQL-endpoint id
(cross-plugin) executing-spark, using-duckdb ── etl plugin: ephemeral Spark, local Delta
data items
lakehouses.md · warehouses.md · sql-databases.md · semantic-models.md
└─ all feed querying-data.md (route priority) and notebooks.md (load then read)
governance / deploy
admin.md · permissions.md · tags.md · folders.md
import-download-deploy.md ─ deployment-pipelines.md ─ workspaces.md (git status)
(cross-plugin) audit-tenant-settings ── fabric-admin plugin
Skill references:
- Import, Download, and Deploy - Export / import / copy / move items, PBIP round-trips, dev-to-prod migration patterns
- Querying Data - Query semantic models in DAX and lakehouses or warehouses in SQL with DuckDB
- Lakehouses - Endpoints, file/table operations, OneLake paths
- Warehouses - Create, browse, query via DuckDB, load data
- SQL Databases - Create, browse, query via DuckDB, auto-mirroring
- Semantic Models - TMDL, DAX, refresh, storage mode
- Reports - Export, import, visuals, fields, and the server-side
ExportTo render that substitutes for a Power BI Desktop screenshot where Desktop is unavailable
- Paginated Reports - RDL upload, export-to-file, datasources, parameters
- Notebooks - Python/PySpark kernels, metadata, cell CRUD, Livy execution, scheduling
- Workspaces - Create, manage, permissions
- Permissions - Sharing and distribution, workspace roles, item permissions, apps, embed, B2B, deployment pipeline permissions, licensing and capacity SKUs
- [Deployment Pipe
…(truncated)
1---2name: fabric-cli3description: Expert guidance for using the Fabric CLI (`fab`) to fully interact with Fabric workspaces, items, and configuration. Automatically invoke this skill whenever the user mentions "Fabric" or "Power BI Service" or a "Fabric/Power BI workspace".4---56# Fabric CLI78Guidance for using `fab` to programmatically manage Fabric & Power BI service910- Install via `uv tool install ms-fabric-cli` (get `uv` via `winget install uv` or `brew install uv`)11- Fabric CLI is for working with the Cloud environment and not local files; it works with Power BI Pro, PPU, or Fabric; you DO NOT need a Fabric SKU to use the Fabric CLI12- Keep `fab` current: check the installed version against the latest `ms-fabric-cli` release and upgrade with `uv tool upgrade ms-fabric-cli` unless the user has pinned a specific version. Discover commands and flags with `fab --help` and `fab <command> --help` rather than hard-coding behavior; the CLI surface changes regularly1314> [!IMPORTANT]15> When you learn something generic about `fab` (an error and its real cause, a request shape the16> docs get wrong, an undocumented response envelope, a prerequisite that is not written down),17> record it where it will still be true for the next reader. Service and API behaviour goes in the18> `references/*.md` file that already owns that topic; the reference map at the end of this file is19> the index. Anything that names an operating system, a shell, an installed binary or a `fab`20> version carries its scope in the sentence, per the boundary rule below.21>22> This skill folder is the only copy that ships. A note in a per-agent memory file is per-machine23> and per-user, so a second machine, a Codespace, and everyone else running this plugin never see it.24>25> Generic learnings only, never item- or task-specific ones. Do not write a change log. If the fact26> is already in the skill, improve the one copy rather than restating it somewhere else.2728<!-- boundary-rule:begin -->29## Where a new learning goes3031Three questions, in order. Stop at the first yes.3233**1. Is it true only because of how THIS machine is set up right now?**34An installed path, which identity you are logged in as, a preview toggle, a console codepage, which35build happens to be installed. Then it is machine-local.3637Before accepting that answer, try to generalise it. Most machine-local facts are the residue of a38search that succeeded once, and the search is the portable part:3940| Instead of recording | Record |41| --- | --- |42| the path where you found a DLL | the probe that finds it, and how to tell which host can load it |43| that a preview toggle is off here | the verbatim symptom string, and the route that works regardless |44| which account has rights here | the check that reveals the mismatch |45| that a script cannot find a binary | a fix to the script |4647If the generalised form survives, it is not machine-local: take it to question 2 or 3. If nothing48survives, because the fact is about one machine, one tenant or one person, write it to the agent's49own memory file and nowhere else. It would mislead an agent anywhere else, and this repository is50public.5152**A Codespace has no legitimate machine-local layer.** A fact about a Codespace is true of every53Codespace built from the same devcontainer, which makes it a fact about that image. Commit it.54Never start a memory file inside a container.5556**2. Is it true only where Power BI Desktop runs, only in a Windows shell, or only at some tool57version?**58Then it is portable knowledge with a boundary. It goes in this skill's `references/`, with the59boundary in the sentence:6061- Platform: open or close with the scope. "On a cp1252 Windows console ... Linux and macOS never62 hit this." "Power BI Desktop only."63- Version: write the symptom and the check as the instruction, never the version. "If `fab find`64 errors, run `fab --version` before assuming a syntax problem." Put the version and date you65 observed in brackets at the end, never in the imperative. A version in the imperative rots into a66 lie; a version in brackets rots into a footnote.67- A dated or version-pinned claim also carries a `Retest:` line naming the one command that settles68 it, plus a `Verified <date>` stamp. `scripts/check-skill-hygiene.py` reports the stale ones and69 fails on a version claim with no `Retest:`.7071**A scoped statement that is a ROUTE is not finished until it names the substitute in the same72sentence.** "`pbir desktop screenshot` is Windows and Desktop only" leaves a Linux agent stuck.73"`pbir desktop screenshot` is Windows and Desktop only; where Desktop is unavailable, render74server-side with the `ExportTo` API (fabric-cli `references/reports.md`)" does not.7576**3. Otherwise it is a fact about the file format, the product, or the service API.**77True everywhere, including a Codespace with no Desktop and no Windows. It goes in this skill's78`references/` with no qualifier, or in `SKILL.md` when the agent must know it before opening any79reference. This is the default and where most learnings land.8081### Two tests that settle almost every case8283- *Would this sentence still be true in a Linux Codespace with no Power BI Desktop?* Yes means84 question 3. No, but only because Desktop is missing, means question 2. No, because the sentence85 names a path, a version or a toggle, means question 1, so run the generalisation table first.86- *Could anyone else running this plugin act on it?* If not, question 1.8788### When torn, file it in the more public place8990An over-cautious scope clause on a portable fact costs a reader one clause. A machine-local fact91shipped as product knowledge misleads everyone who installs the plugin.9293### Where to write it9495If `PBI_MARKETPLACE_ROOT` is set, a writable clone of this marketplace is on the machine:96`bash "$PBI_MARKETPLACE_ROOT/scripts/record-learning.sh"` writes the note, runs the hygiene scan,97commits to a branch and opens a pull request.9899If it is unset, the skills are loading from a read-only plugin cache and an edit there is discarded100by the next `plugin update`. Write the note to the agent's memory file instead, and say plainly in101the note that it still needs promoting into the plugin.102103Nothing portable belongs in `~/.claude/rules/`, `.cursor/rules/` or `.github/instructions/`. Those104are per-machine and per-user.105<!-- boundary-rule:end -->106107## When to use this skill108109- Use whenever the user mentions "Fabric" or "Power BI"110- Use when user asks about Power BI workspaces, deployment, tenants, publishing, download, permissions, or data111112113## Critical general rules114115- IMPORTANT: The first time you use `fab` run check that it is up to date to the latest version (upgrade with `uv tool upgrade ms-fabric-cli` unless the user has pinned a version) and run `fab auth status`; If user isn't authenticated, ask them to run `fab auth login`116- On a Windows console left on the cp1252 codepage, `fab` dies part-way through its own output with `'charmap' codec can't encode character` even though the server-side work succeeded; export `PYTHONIOENCODING=utf-8` and `PYTHONUTF8=1` in every shell block that calls `fab` (details in [reference.md](./references/reference.md#console-encoding-on-windows)). Linux and macOS never hit this117- Always use `fab --help` and `fab <command> --help` the first time you use a command to understand its syntax118- You must search the skill /references/ for relevant reference files that explain certain commands, examples, scripts, or workflows before you start using `fab`119- Before first use, ask the user if they have Fabric admin access, sensitivity labels or DLP policies, any API restrictions, or preferences for Fabric/Power BI API usage; remind user to add this to memory files120- If workspace or item name is unclear, ask the user first, then verify with `fab ls` or `fab exists` before proceeding121- Ensure that you avoid removing or moving items, workspaces, or definitions, or changing properties without explicit user direction122- If a command is blocked in your permissions and you try to use it, stop and ask the user for clarification; never try to circumvent it123- Create output directories before export: `fab export` does not create intermediate directories; `mkdir -p` the output path first or the command fails with `[InvalidPath]`124125126### Use `-f` (force) for non-interactive use127128The `fab` CLI prompts for confirmation, so you **you must always append `-f`** to prevent this UNLESS sensitivity labels are enabled, in which case you must ask the user. Do this for the commands:129130- `fab get -q "definition"` ; sensitivity label confirmation131- `fab export` ; sensitivity label confirmation132- `fab import` ; overwrite confirmation133- `fab cp` / `fab cp -r` ; overwrite and sensitivity label confirmation134- `fab rm` ; delete confirmation135- `fab assign` / `fab unassign` ; capacity/domain assignment confirmation136- `fab mv` ; rename/move confirmation137138139## Quickstart guide140141You must read and understand the common list of operations with simple examples1421430. Check the commands, syntax, and auth status: `fab --help` and `fab auth status`1441. Check if the item exists if the user gave the workspace and item name: `fab exists "spaceparts-dev.Workspace/spaceparts-otc-full.SemanticModel"`1452. Find an item by name across every workspace the user can see: `fab find 'sales' -P type=Report -l` (substring on name, description, workspace; `-P type=` to filter, `-l` for ids; `-q '<jmespath>'` for client-side filter/projection). For governance workflows that need last visit / last refresh / owner / storage mode / capacity SKU, use [`scripts/search_across_workspaces.py`](./scripts/search_across_workspaces.py); see [workspaces.md](./references/workspaces.md#cross-workspace-search) for the delta.1463. Find the workspace: `fab ls`1474. Find the item: `fab ls "Workspace Name.Workspace"`1484. Check the commands for that item: 149 - `fab desc` to get itemTypes150 - `fab desc .<ItemType>` for commands i.e. `fab desc .SemanticModel`1515. What's in that item; what's it for; what is it?:152 - Full TMDL definition: `fab get "spaceparts-dev.Workspace/spaceparts-otc-full.SemanticModel" -q "definition" -f`153 - Search a specific measure / table / column: `fab get "ws.Workspace/Model.SemanticModel" -q "definition" -f | rga -i "Sales Amount"`154 - Retrieve AI instructions / AI schema: `python3 scripts/get_semantic_model_ai_metadata.py "ws.Workspace/Model.SemanticModel" --instructions-out instructions.md --schema-out schema.json`1556. Get files, tables, or table schemas:156 - List lakehouse files: `fab ls "ws.Workspace/LH.Lakehouse/Files"`157 - List lakehouse tables: `fab ls "ws.Workspace/LH.Lakehouse/Tables"`158 - Table schema: `fab table schema "ws.Workspace/LH.Lakehouse/Tables/gold/orders"`1597. Query data (always prefer the wrapper scripts over raw `fab api` / `duckdb` / `sqlcmd`; they resolve IDs, hosts, and auth for you):160 - Semantic model (DAX): `python3 scripts/execute_dax.py "ws.Workspace/Model.SemanticModel" -q "EVALUATE TOPN(10, 'Orders')"`161 - Lakehouse SQL endpoint, warehouse, or SQL database (T-SQL): prefer the `fabric-sql` MCP `execute_query(workspaceId, itemId, query)` when it is loaded; fall back to `python3 scripts/query_sql_endpoint.py "ws.Workspace/LH.Lakehouse" -q "SELECT TOP 10 * FROM dbo.orders"`. See [querying-data.md](./references/querying-data.md#querying-the-sql-endpoint-route-priority)162 - Lakehouse or warehouse Delta over OneLake (DuckDB): `python3 scripts/query_lakehouse_duckdb.py "ws.Workspace/LH.Lakehouse" -q "SELECT * FROM tbl LIMIT 10" -t gold.orders`1638. Set properties for an item or workspace: `fab set "ws.Workspace/Item.Notebook" -q displayName -i "New Name"` or `fab set "ws.Workspace" -q description -i "Production environment"`1649. Review or manage permissions:165 - Item ACL: `fab acl ls "ws.Workspace/Model.SemanticModel"` then `fab acl set "ws.Workspace/Model.SemanticModel" -I user@contoso.com -R Read`166 - Workspace roles: `fab acl ls "ws.Workspace"` then `fab acl set "ws.Workspace" -I user@contoso.com -R Member`167 - Setting up a service principal for automation instead of a human identity: [service-principals.md](./references/service-principals.md) - creation via az CLI, the workspace-role-plus-tenant-setting-group double requirement, and how to authenticate `fab` as it16810. Deploy items to Fabric: `fab import "ws.Workspace/New.Notebook" -i ./local-path/Nb.Notebook -f`16911. Download items from Fabric: `fab export "ws.Workspace/Nb.Notebook" -o ./backup -f` (always `mkdir -p ./backup` first)17012. Copy or move items between workspaces: `fab cp "dev.Workspace/Item.Notebook" "prod.Workspace" -f` or `fab mv "ws.Workspace/Old.Notebook" "ws.Workspace/New.Notebook" -f`17113. Open item in Fabric via browser: `fab open "spaceparts-dev.SpaceParts/Amazing Report.Report"`17214. Using Fabric or Power BI APIs: `fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}'` or `fab api "workspaces/<ws-id>/items"`17315. Using [Azure CLI](./references/fab-vs-az-cli.md) (advanced) when Fabric CLI doesn't suffice:174 - T-SQL over any SQL-capable item ; use [`scripts/query_sql_endpoint.py`](./scripts/query_sql_endpoint.py) (reuses `az login` via `ActiveDirectoryAzCli`; full walkthrough in [querying-data.md](./references/querying-data.md#sqlcmd-over-lakehouse-warehouse-and-sql-database))175 - Pass a Key Vault secret to a consumer without ever reading, echoing, or persisting it: `az login --service-principal -u <appId> -t <tenantId> --password "$(az keyvault secret show --vault-name <vault> --name <secret> --query value -o tsv)"` ; command substitution pipes the secret directly into the child process arg list, never stdout, a file, or a named shell variable176 - Calling `az` from a Python script on Windows needs two accommodations that Linux and macOS do not: resolve the executable with `shutil.which("az")` so `PATHEXT` is honoured, and pass the command as one string with `shell=True` under Git Bash ; [fab-vs-az-cli.md](./references/fab-vs-az-cli.md#calling-az-from-a-script)177 - Full fab-vs-az decision matrix: [fab-vs-az-cli.md](./references/fab-vs-az-cli.md)178179180## Essential Concepts181182For information about any concepts related to Power BI or Fabric you must search or fetch via the `microsoft-learn` MCP server (or the `pbi-search` CLI as an alternative) and ask the user questions with the `AskUserQuestion` tool; NEVER guess or make assumptions.183184### Workspaces185186- **Workspaces** are containers for **items** like Notebooks (and other ETL items), Lakehouses (and other data items), SemanticModels, Reports (and other consumption items), and OrgApps.187- Workspaces can be assigned to different things:188 - Deployment Pipelines for lifecycle management (Dev, Test, Prod, etc.)189 - Domains for governance and tenant structuring190 - Capacities for licensing and resources (Fabric or Premium capacities only; PPU and Pro work differently)191 - Git repositories for Source Control via Git integration192193194## Key Patterns195196Pay special attention to each of the following areas when using the Fabric CLI197198199### Path Format200201Fabric uses filesystem-like paths with type extensions:202203`"WorkspaceName.Workspace/ItemName.ItemType"`204205You must quote paths with spaces and punctuation:206207`"Workspace Name.Workspace/Semantic Model Name.SemanticModel"`208209For lakehouses this is extended into files and tables:210211`WorkspaceName.Workspace/LakehouseName.Lakehouse/Files/FileName.extension` or `/WorkspaceName.Workspace/LakehouseName.Lakehouse/Tables/TableName`212213For Fabric capacities you have to use `fab ls .capacities`214215Examples:216217- `"Production Workspace.Workspace/Sales Report.Report"`218- `Data.Workspace/MainLH.Lakehouse/Files/data.csv`219- `Data.Workspace/MainLH.Lakehouse/Tables/dbo/customers`220221222### Common Item Types223224- `.Workspace` - Workspaces225- `.SemanticModel` - Power BI datasets226- `.Report` - Power BI reports227- `.Notebook` - Fabric notebooks228- `.DataPipeline` - Data pipelines229- `.Lakehouse` / `.Warehouse`/ `.SQLDatabase` - Data artifacts230- `.SparkJobDefinition` - Spark jobs231- `.AISkill` - Fabric Data Agents232- `.MirroredDatabase` / `.MirroredWarehouse` - Mirrored databases233- `.Environment` - Spark environments234- `.UserDataFunction` - User data functions235236Full list: You must use `fab desc` or `fab desc .<ItemType>` to check syntax and types if the user asks about an item type not listed above.237238239### JMESPath Queries240241Filter and transform JSON responses with `-q`:242243```bash244# Get single field245-q "id"246-q "displayName"247248# Get nested field249-q "properties.sqlEndpointProperties"250-q "definition.parts[0]"251252# Filter arrays253-q "value[?type=='Lakehouse']"254-q "value[?contains(name, 'prod')]"255256# Get first element257-q "value[0]"258-q "definition.parts[?path=='model.tmdl'] | [0]"259```260261### Using `fab api`262263`fab` has an api escape hatch that lets you use any API even if it doesn't have primary commands.264265266#### Variable Extraction Pattern267268To use `fab api` you need item IDs. Extract them like this:269270```bash271WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')272MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')273274# Then use in API calls275fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'276```277278279#### Admin APIs (Requires Admin Role)280281Don't use admin commands or APIs if the user doesn't have Admin access. Here's some examples:282283```bash284# Find semantic models by name (cross-workspace)285fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name, 'Sales')]"286287# Find all notebooks288fab api "admin/items" -P "type=Notebook" -q "itemEntities[].{name:name,workspace:workspaceId}"289290# Find all lakehouses291fab api "admin/items" -P "type=Lakehouse"292293# Common types: SemanticModel, Report, Notebook, Lakehouse, Warehouse, DataPipeline, Ontology294```295296For full admin API reference (cross-workspace discovery, tenant settings read/update, capacity/domain/workspace overrides, activity events): [admin.md](./references/admin.md)297298299### Error Handling & Debugging300301```bash302# Show response headers303fab api workspaces --show_headers304305# Verbose output306fab get "Production.Workspace/Item" -v307308# Save responses for debugging (fab api has no -o flag; redirect stdout)309fab api workspaces > /tmp/workspaces.json310```311312313## Common workflows314315These are the most common workflows you'll encounter in Fabric316317### Finding or exploring workspaces, items, or metadata318319| Command | Purpose | Example |320|---|---|---|321| `fab ls` | List workspaces / items | `fab ls "Sales.Workspace" -l` |322| `fab exists` | Check if a path exists | `fab exists "Sales.Workspace/Model.SemanticModel"` |323| `fab get` | Get item details | `fab get "Sales.Workspace" -q "id"` |324| `fab desc` | Supported commands per type | `fab desc .SemanticModel` |325326Flags:327- `-l` (long listing)328- `-a` (show hidden items)329- `-q` (JMESPath filter)330- `-v` (verbose output)331- `-o` (save response to file)332333Fabric discovery follows a drill-down pattern:334335- Browsing:336 - List workspaces: `fab ls`337 - List items in a workspace: `fab ls "ws.Workspace" -l`338 - Confirm a path exists: `fab exists "ws.Workspace/Item"`339 - Check what commands an item type supports: `fab desc .<ItemType>`340- Inspection:341 - Get item details: `fab get "ws.Workspace/Item"`342 - Pull a single field: `fab get "ws.Workspace" -q "id"`343- Cross-workspace search:344 - Routine search across name, description, workspace: `fab find '<text>' -P type=<Type> -l`345 - Governance fields not in `fab find` (last visit, last refresh, owner, storage mode, capacity SKU, Copilot readiness): [`scripts/search_across_workspaces.py`](./scripts/search_across_workspaces.py); see [workspaces.md](./references/workspaces.md#cross-workspace-search) for the delta346 - Downstream reports for a given model: [`scripts/get-downstream-reports.py`](./scripts/get-downstream-reports.py)347 - Tenant-wide admin APIs: [admin.md](./references/admin.md)348349Check references before exploring:350351- [workspaces.md](./references/workspaces.md)352- [folders.md](./references/folders.md)353- [admin.md](./references/admin.md)354- [reference.md](./references/reference.md)355356357### Querying data358359| Command | Purpose | Example |360|---|---|---|361| `fab get -q "definition"` | Get model schema | `fab get "ws.Workspace/Model.SemanticModel" -q "definition" -f` |362| `fab api -A powerbi` | Execute DAX | `fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE..."}]}'` |363| `fab ls` | Browse files / tables | `fab ls "ws.Workspace/LH.Lakehouse/Files"` |364| `fab table schema` | Lakehouse table schema | `fab table schema "ws.Workspace/LH.Lakehouse/Tables/sales"` |365| `fab cp` | Upload / download OneLake file | `fab cp ./local.csv "ws.Workspace/LH.Lakehouse/Files/"` |366| `duckdb` + `delta_scan` | Query Delta tables (requires DuckDB) | `duckdb -c "... delta_scan('abfss://<ws-id>@onelake.../<lh-id>/Tables/schema/table')"` |367| `duckdb` + `read_csv/json` | Query raw files (requires DuckDB) | `duckdb -c "... read_csv('abfss://.../Files/data.csv')"` |368369Flags: 370- `-A fabric|powerbi|storage|azure` (API audience)371- `-X get|post|put|delete|patch` (HTTP method)372- `-i` (JSON body or file)373- `-f` (skip sensitivity prompt on definition pulls).374375Fabric exposes three query paths depending on the source; always prefer the wrapper scripts -- they resolve IDs, hosts, and auth for you:376377- Semantic models (DAX):378 - Find model fields first: `fab get "ws.Workspace/Model.SemanticModel" -q "definition"`379 - Query: [`scripts/execute_dax.py`](./scripts/execute_dax.py)380- Lakehouses / Warehouses via Delta over OneLake (DuckDB):381 - Query a single table: [`scripts/query_lakehouse_duckdb.py`](./scripts/query_lakehouse_duckdb.py) (use `tbl` as a placeholder and pass `-t schema.table`)382 - Multi-table joins or raw files in `Files/`: pass `--sql` with your own `delta_scan()` / `read_csv` / `read_json_auto` calls383 - Optionally scaffold a Direct Lake model instead: [`scripts/create_direct_lake_model.py`](./scripts/create_direct_lake_model.py)384- Lakehouse SQL endpoint, Warehouse, or SQL Database (T-SQL):385 - Prefer the `fabric-sql` MCP `execute_query(workspaceId, itemId, query)` when loaded; server-side, no local tooling386 - Fall back to [`scripts/query_sql_endpoint.py`](./scripts/query_sql_endpoint.py) (`sqlcmd`; auto-detects host per item type, reuses `az login` via `ActiveDirectoryAzCli`) when the MCP is unavailable387 - Prefer either over DuckDB when you need `INFORMATION_SCHEMA`, `sys.*` metadata, CTEs, or window functions388 - Full route priority: [querying-data.md](./references/querying-data.md#querying-the-sql-endpoint-route-priority)389390Check references before writing queries:391392- [querying-data.md](./references/querying-data.md)393- [semantic-models.md](./references/semantic-models.md)394- [lakehouses.md](./references/lakehouses.md)395- [warehouses.md](./references/warehouses.md)396- [sql-databases.md](./references/sql-databases.md)397398399### Changing metadata or access (descriptions, tags, endorsement, properties, bindings, permissions)400401| Command | Purpose | Example |402|---|---|---|403| `fab set` | Update property | `fab set "ws.Workspace/Item" -q displayName -i "New Name"` |404| `fab mv` | Rename / move item | `fab mv "ws/Old.Notebook" "ws/New.Notebook" -f` |405| `fab acl ls` | List permissions | `fab acl ls "ws.Workspace"` |406| `fab acl set` | Grant permission | `fab acl set "ws.Workspace" -I <objectId> -R Member` |407| `fab acl rm` | Revoke permission | `fab acl rm "ws.Workspace" -I <upn>` |408| `fab label set` | Set sensitivity label | `fab label set "ws/Nb.Notebook" --name Confidential` |409410Flags:411- `-q <field>` + `-i <value>` (set a single property)412- `-I` (object ID or UPN for `fab acl`)413- `-R Admin|Member|Contributor|Viewer` (role for `fab acl set`)414- `-f` (skip confirmation; ask user first if sensitivity labels are in play)415416Metadata and access changes fall into a few groups:417418- Properties (displayName, description, sensitivity config):419 - Native update: `fab set "<path>" -q <field> -i "<value>"`420 - Capture current state first so you can revert: `fab get -v -o /tmp/before.json`421- Endorsement, certification, and tags (no first-class `fab` commands):422 - Patch via `fab api` with item-specific endpoints423 - Tag workflow: [tags.md](./references/tags.md)424 - Endorsement patterns: [reference.md](./references/reference.md)425- Folder placement:426 - Move items between workspace subfolders: [folders.md](./references/folders.md)427- Access control and sensitivity labels:428 - Grant / revoke: `fab acl set`, `fab acl rm`429 - Set sensitivity label: `fab label set`430 - Verify the principal first: `az ad user show`431 - Never change permissions or labels without explicit user confirmation432- Bindings:433 - Rebind a thin `.Report` to a different `.SemanticModel`: [reports.md](./references/reports.md)434 - Semantic model source rebinds (e.g. swap a lakehouse): [semantic-models.md](./references/semantic-models.md)435436Check references before changing metadata:437438- [reference.md](./references/reference.md)439- [tags.md](./references/tags.md)440- [folders.md](./references/folders.md)441- [reports.md](./references/reports.md)442- [semantic-models.md](./references/semantic-models.md)443444### Working with workspaces445446| Command | Purpose | Example |447|---|---|---|448| `fab mkdir` | Create workspace / item | `fab mkdir "New.Workspace" -P capacityname=MyCapacity` |449| `fab assign` | Attach capacity / domain | `fab assign .capacities/cap.Capacity -W ws.Workspace -f` |450| `fab unassign` | Detach capacity / domain | `fab unassign .capacities/cap.Capacity -W ws.Workspace` |451| `fab start` / `fab stop` | Resume / pause capacity | `fab start .capacities/cap.Capacity` |452| `fab cp -r` | Fork workspace | `fab cp "dev.Workspace" "prod.Workspace" -r -f` |453| `fab rm` | Soft-delete (see [recovery](./references/reference.md#recovering-deleted-items)) | `fab rm "ws/Item.Type" -f` |454455Flags:456- `-P key=value` (creation params for `fab mkdir`)457- `-W` (target workspace for `fab assign` / `fab unassign`)458- `-r` (recursive copy/move)459- `-bpc` (block on path collision for `fab cp`)460- `-f` (skip confirmation)461462Workspace-scope operations fall into a few groups:463464- Create and provision:465 - Create workspace: `fab mkdir "<Name>.Workspace" -P capacityname=<cap>`466 - Attach capacity or domain: `fab assign .capacities/<cap>.Capacity -W <ws>.Workspace`467 - Planning context, create/get/set surface, large storage format, Spark pools, OneLake defaults, Git: [workspaces.md](./references/workspaces.md)468- Copy, fork, download:469 - Duplicate a workspace in-tenant: `fab cp -r "dev.Workspace" "prod.Workspace"`470 - Dry-run the source tree first: `fab ls "dev.Workspace"`471 - Full local snapshot (items + lakehouse files): [`scripts/download_workspace.py`](./scripts/download_workspace.py)472- Permissions:473 - Inspect / grant / revoke: `fab acl ls | set | rm`474 - Tenant-wide governance audit: use the `audit-tenant-settings` skill from the `fabric-admin` plugin475- Connections and gateways (bound to, but outside, the workspace):476 - Credential types (WorkspaceIdentity, SPN, Basic), OAuth2 limits: [connections.md](./references/connections.md)477 - Datasource binding, credential rotation: [gateways.md](./references/gateways.md)478- Folders inside a workspace:479 - Layout, nesting, conventions: [folders.md](./references/folders.md)480481Check references before modifying workspaces:482483- [workspaces.md](./references/workspaces.md)484- [folders.md](./references/folders.md)485- [connections.md](./references/connections.md)486- [gateways.md](./references/gateways.md)487488489### Executing or scheduling jobs (notebooks, notebook cells, pipelines, semantic model refresh)490491| Command | Purpose | Example |492|---|---|---|493| `fab job run` | Run synchronously | `fab job run "ws/ETL.Notebook" -P date:string=2025-01-01` |494| `fab job start` | Run asynchronously | `fab job start "ws/ETL.Notebook"` |495| `fab job run-list` | List executions | `fab job run-list "ws/Nb.Notebook"` |496| `fab job run-status` | Check status | `fab job run-status "ws/Nb.Notebook" --id <job-id>` |497| `fab job run-cancel` | Cancel a job | `fab job run-cancel "ws/Nb.Notebook" --id <job-id> -w` |498| `scripts/run_notebook_checked.py` | Run a notebook + verify its exit value (status `Completed` ≠ ETL succeeded) | `python3 scripts/run_notebook_checked.py "ws/ETL.Notebook"` |499| `fab api -A powerbi .../refreshes` | Trigger semantic model refresh | `fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}'` |500501Flags:502- `-P key:type=value` (parameters, type is `string|int|bool`)503- `--id` (job run ID)504- `-w` (wait on cancel)505- `--timeout` (overall timeout for synchronous runs; it can crash the client poller with `'<' not supported between instances of 'int' and 'str'` while the job still runs server-side, so do not resubmit, see [notebooks.md](./references/notebooks.md#running-notebooks))506- `--polling_interval` (status poll cadence)507508Jobs map to different endpoints depending on item type:509510- Notebooks and pipelines:511 - Run synchronously: `fab job run "ws/ETL.Notebook" -P date:string=2025-01-01`512 - Run asynchronously: `fab job start "ws/ETL.Notebook"`513 - Check status: `fab job run-status "ws/Nb.Notebook" --id <job-id>`514 - List history: `fab job run-list "ws/Nb.Notebook"`515 - Verify the REAL outcome: a job `Completed` only means the process finished -- a notebook can catch its own exception and exit a failure payload while still showing `Completed`. Read its exit value, or use [`scripts/run_notebook_checked.py`](./scripts/run_notebook_checked.py); details in [notebooks.md](./references/notebooks.md#the-notebooks-exit-value-the-only-reliable-success-signal)516 - Python / PySpark kernels, Livy sessions, cell-level CRUD: [notebooks.md](./references/notebooks.md)517- Semantic model refresh (not exposed as `fab job`):518 - Trigger: `fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes" -X post -i '{"type":"Full"}'`519 - Check current run before starting a new one (409 if already running): `fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes?\$top=1"`520 - Enhanced refresh, incremental policies, partition targeting: [semantic-models.md](./references/semantic-models.md)521- Dataflow refresh:522 - Gen1 and Gen2 have different endpoints: [dataflows.md](./references/dataflows.md)523- Scheduling:524 - Per-item schedules via the scheduler API: [notebooks.md](./references/notebooks.md), [reference.md](./references/reference.md)525526Check references before running jobs:527528- [notebooks.md](./references/notebooks.md)529- [semantic-models.md](./references/semantic-models.md)530- [dataflows.md](./references/dataflows.md)531- [reference.md](./references/reference.md)532533534### Fabric admin operations (auditing, management)535536| Command | Purpose | Example |537|---|---|---|538| `fab api "admin/items"` | Cross-workspace item search | `fab api "admin/items" -P "type=SemanticModel" -q "itemEntities[?contains(name,'Sales')]"` |539| `fab api "admin/workspaces"` | Workspace inventory | `fab api "admin/workspaces"` |540| `fab api "admin/tenantsettings"` | Tenant settings | `fab api "admin/tenantsettings"` |541| `fab api "admin/capacities"` | Capacity inventory | `fab api "admin/capacities"` |542| `fab api -X post .../update` | Update tenant setting | `fab api -X post "admin/tenantsettings/<name>/update" -i body.json` |543544Flags:545- `-P key=value` (query params, e.g. `type=SemanticModel`)546- `-q` (JMESPath filter)547- `-X post` + `-i` (write ops)548- `--show_headers` (inspect `Retry-After` on 429)549550Admin-scope work is gated behind the Fabric / Power BI admin role. Confirm access first with `fab api "admin/capacities" 2>&1 | head -5`; if it errors, stop rather than retry.551552Two entry points cover most admin tasks:553554- Governance audits (tenant settings, delegated overrides, Entra SG scoping):555 - Use the `audit-tenant-settings` skill from the `fabric-admin` plugin. It owns the curated metadata baseline, the audit + change-detection script, delegated-override enumeration, and the Entra SG investigation workflow.556 - Invoke it whenever the question combines tenant posture with group membership, override scope, or drift against the baseline.557- Raw admin APIs (cross-workspace search, activity events, artifact access, item search):558 - Patterns in [admin.md](./references/admin.md)559 - Rate limit: 25 write requests / minute; honor `Retry-After` on 429560 - Print the exact command and wait for user confirmation before any destructive admin operation561562Check references before admin work:563564- [admin.md](./references/admin.md)565- [permissions.md](./references/permissions.md) for workspace / item ACL exposure audits566567568### Definitions and deployment (item definitions, deployment pipelines, git integration, cicd)569570| Command | Purpose | Example |571|---|---|---|572| `fab get -q "definition"` | Read raw definition | `fab get "ws/Model.SemanticModel" -q "definition" -f` |573| `fab export` | Export item to local | `fab export "ws/Nb.Notebook" -o ./backup -f` |574| `fab import` | Import item from local | `fab import "ws/Nb.Notebook" -i ./backup/Nb.Notebook -f` |575| `fab cp` | Copy between workspaces | `fab cp "dev/Item" "prod.Workspace" -f` |576| `fab api "deploymentPipelines"` | Deployment pipelines API | `fab api "deploymentPipelines" -q "value[]"` |577578Flags:579- `-o` (output path for `fab export`)580- `-i` (input path or JSON body for `fab import`)581- `--format` (definition format for export / import)582- `-f` (skip overwrite and sensitivity prompts)583584> [!IMPORTANT]585> **The poll interval is by far the biggest performance lever for any definition change.**586> Creating or updating an item definition is a long-running operation (LRO): the API returns587> `202 Accepted` with a `Retry-After: 20` header. `fab import`, `nb create`, and `nb cell edit`588> wait roughly that long between status polls, so a notebook that the server finishes in ~1s589> takes them 25-60s. Neither `fab` nor `nb` exposes a knob to change that interval.590> For notebook definition changes, strongly prefer [`scripts/deploy_notebook.py`](./scripts/deploy_notebook.py),591> which polls the LRO every ~0.3s (tunable via `--poll-interval`) and creates in ~1-2s or updates592> in place in ~1s. Auto-detects create vs update. When you must roll your own for another item593> type, the rule is the same: poll `updateDefinition` / create at ~0.3s, not the advertised 20s.594> ```bash595> python3 scripts/deploy_notebook.py "ws.Workspace/ETL.Notebook" -i ./ETL.Notebook # create or update in place596> ```597598Every Fabric item has a serializable definition. Move definitions between environments depending on scope:599600- Single item:601 - Round-trip locally: `fab export` then `fab import` (always `mkdir -p` the output directory first; `fab export` does not create intermediate directories and fails with `[InvalidPath]`)602 - For a `.SemanticModel` there is a second caveat: `fab export` omits `definition.pbism` and `fab import` requires it, so write `{"version":"4.2","settings":{}}` to the item root before importing or the import fails with `Workload_FailedToParseFile ... Required artifact is missing in 'definition.pbism'`; see [import-download-deploy.md](./references/import-download-deploy.md#export-output-structure)603 - Same-tenant shortcut, no local hop: `fab cp "dev/Item" "prod.Workspace"`604- Semantic model as PBIP (TMDL + blank report):605 - Export the model with `fab export`, create the report with `pbir new report`, then combine606 them with `pbir report merge-to-thick`; see [import-download-deploy.md](./references/import-download-deploy.md)607- Full workspace snapshot (items + lakehouse files):608 - Backups, offline analysis, cross-tenant forks: [`scripts/download_workspace.py`](./scripts/download_workspace.py)609- Promotion between Dev, Test, Prod:610 - Fabric deployment pipelines API (covers all item types)611 - Power BI pipelines API (Power BI items only, but finer-grained deploy flags like `allowPurgeData`, `allowTakeOver`)612 - When to use each, selective deploy, LRO polling: [deployment-pipelines.md](./references/deployment-pipelines.md)613- Git integration (connect workspace to repo, branch, commit, update from git):614 - Workspace git section in [workspaces.md](./references/workspaces.md)615616Check references before deploying:617618- [import-download-deploy.md](./references/import-download-deploy.md) ; export / import / copy / move, PBIP round-trips, migration patterns, rebinding gotchas619- [deployment-pipelines.md](./references/deployment-pipelines.md)620- [semantic-models.md](./references/semantic-models.md)621- [reports.md](./references/reports.md) ; includes the server-side `ExportTo` render for verifying a deployed report without Power BI Desktop622- [paginated-reports.md](./references/paginated-reports.md)623- [notebooks.md](./references/notebooks.md)624- [workspaces.md](./references/workspaces.md)625626627## Related skills628629- `audit-tenant-settings` (in the `fabric-admin` plugin) ; Fabric governance workflow covering tenant settings, delegated overrides (capacity / domain / workspace), and the Entra security groups those settings reference. Read-only; holds the curated metadata baseline and the audit + change-detection script.630631## Gotchas632633- **IMPORTANT:** DON'T try to use `fab ls` on items that aren't data items (.Lakehouse, .Warehouse, etc); use `fab ls` to find workspaces and items, and use `fab get` to look at definitions634- ALWAYS Use the `-f` flag when using `fab get`, `fab import`, `fab export`, etc. as described above635- ONLY fallback to `fab api` when a command doesn't exist636- **`fab api` returns a `{status_code, text}` envelope, not the raw body:** `-q` filters must start with `text.` or they silently return `None`, there is no `-o` flag (redirect stdout), and binary bodies (PDF, PNG, XLSX, PBIX, `.rdl`) are corrupted, so fetch files over raw HTTP with an `az` bearer token. See [fab-api.md](./references/fab-api.md#output-shape-and-flags)637- **Definition changes feel slow but aren't:** `fab import` / `nb create` / `nb cell edit` take 25-60s to push a notebook definition only because they poll the LRO at the server's `Retry-After: 20`. The work is ~1s. Use [`scripts/deploy_notebook.py`](./scripts/deploy_notebook.py) (tight-polls at ~0.3s) for definition changes; the poll interval is the single biggest lever638639## References640641**Reference map** (which references cluster together; follow the links between them, not just this list):642643```644etl / notebooks645 notebooks.md ── run jobs, exit value, scheduling646 ├─ querying-data.md ── nb exec / Livy, DuckDB/sqlcmd, SQL-endpoint sync647 └─ lakehouses.md ── attach, table ops, OneLake shortcuts, SQL-endpoint id648 (cross-plugin) executing-spark, using-duckdb ── etl plugin: ephemeral Spark, local Delta649650data items651 lakehouses.md · warehouses.md · sql-databases.md · semantic-models.md652 └─ all feed querying-data.md (route priority) and notebooks.md (load then read)653654governance / deploy655 admin.md · permissions.md · tags.md · folders.md656 import-download-deploy.md ─ deployment-pipelines.md ─ workspaces.md (git status)657 (cross-plugin) audit-tenant-settings ── fabric-admin plugin658```659660**Skill references:**661662- [Import, Download, and Deploy](./references/import-download-deploy.md) - Export / import / copy / move items, PBIP round-trips, dev-to-prod migration patterns663- [Querying Data](./references/querying-data.md) - Query semantic models in DAX and lakehouses or warehouses in SQL with DuckDB664- [Lakehouses](./references/lakehouses.md) - Endpoints, file/table operations, OneLake paths665- [Warehouses](./references/warehouses.md) - Create, browse, query via DuckDB, load data666- [SQL Databases](./references/sql-databases.md) - Create, browse, query via DuckDB, auto-mirroring667- [Semantic Models](./references/semantic-models.md) - TMDL, DAX, refresh, storage mode668- [Reports](./references/reports.md) - Export, import, visuals, fields, and the server-side `ExportTo` render that substitutes for a Power BI Desktop screenshot where Desktop is unavailable669- [Paginated Reports](./references/paginated-reports.md) - RDL upload, export-to-file, datasources, parameters670- [Notebooks](./references/notebooks.md) - Python/PySpark kernels, metadata, cell CRUD, Livy execution, scheduling671- [Workspaces](./references/workspaces.md) - Create, manage, permissions672- [Permissions](./references/permissions.md) - Sharing and distribution, workspace roles, item permissions, apps, embed, B2B, deployment pipeline permissions, licensing and capacity SKUs673- [Deployment Pipe674675…(truncated)