
Fabric Cli Core
- 94 installs
- 163 repo stars
- Updated July 23, 2026
- microsoft/fabric-cli
Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources.
About
Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources. Activate when users mention fab, Fabric CLI, or need to automate Fabric operations. This skill defines safe, consistent defaults for an AI agent helping users operate **Microsoft Fabric** via the **Fabric CLI (`fab`)**.
- This skill defines safe, consistent defaults for an AI agent helping users operate **Microsoft Fabric** via the **Fabric
- ## 1 - Fabric CLI mental model (paths and entities)
- Ready-to-use Python scripts for core CLI tasks. Run any script with `--help` for full options.
- | Script | Purpose | Usage |
- |--------|---------|-------|
Fabric Cli Core by the numbers
- 94 all-time installs (skills.sh)
- Ranked #4,493 of 16,659 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
fabric-cli-core capabilities & compatibility
- Capabilities
- this skill defines safe, consistent defaults for · ## 1 fabric cli mental model (paths and entiti · ready to use python scripts for core cli tasks. · | script | purpose | usage |
- Use cases
- documentation
What fabric-cli-core says it does
Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources. Activate when users mention fab, Fabric CLI, or need to automate Fabric operations.
npx skills add https://github.com/microsoft/fabric-cli --skill fabric-cli-coreAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 94 |
|---|---|
| repo stars | ★ 163 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 23, 2026 |
| Repository | microsoft/fabric-cli ↗ |
How do I apply fabric-cli-core using the workflow in its SKILL.md?
Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources. Activate when users mention fab, Fabric CLI, or need to automate Fabric ope...
Who is it for?
Developers following the fabric-cli-core skill for the tasks it documents.
Skip if: Tasks outside the fabric-cli-core scope described in SKILL.md.
When should I use this skill?
User mentions fabric-cli-core or related triggers from the skill description.
What you get
Working fabric-cli-core setup aligned with the documented patterns and constraints.
Files
Fabric CLI Core
This skill defines safe, consistent defaults for an AI agent helping users operate Microsoft Fabric via the Fabric CLI (`fab`).
1 - Fabric CLI mental model (paths and entities)
Automation Scripts
Ready-to-use Python scripts for core CLI tasks. Run any script with --help for full options.
| Script | Purpose | Usage |
|---|---|---|
health_check.py | Verify CLI installation, auth status, and connectivity | python scripts/health_check.py [--workspace WS] |
Scripts are located in the scripts/ folder of this skill.
Paths and Entities
- Treat Fabric as a filesystem-like hierarchy with consistent dot (.) entity suffixes in paths (e.g.,
.Workspace,.Folder,.SemanticModel). - The hierarchy structure is:
- Tenant: The top-level container for everything.
- Workspace: Personal or team workspace holding folders, items, and workspace-level elements.
- Folder: Container for organizing items within a workspace (supports ~10 levels of nesting).
- Item: Individual resource within a workspace or folder (e.g., Notebook, SemanticModel, Lakehouse).
- OneLakeItem: OneLake storage item residing within a Lakehouse (tables, files, etc.).
- Prefer and generate paths like:
/Workspace1.Workspace/Notebook1.Notebook/Workspace1.Workspace/FolderA.Folder/SemanticModel1.SemanticModel/Workspace1.Workspace/FolderA.Folder/lh1.Lakehouse/Tables(OneLakeItem)- When a user provides an ambiguous identifier, ask for the full path (or infer with stated assumptions).
2 - Modes (interactive vs command line)
- Be explicit about which mode a user is in:
- Interactive mode behaves like a REPL and runs commands without the
fabprefix. - Command line mode runs one command per invocation and is best for scripts/automation.
- The selected mode is preserved between sessions. If a user exits and logs back in, the CLI resumes in the same mode last used.
- When you provide instructions, show commands in command line mode unless the user says they're in interactive mode.
3 - Authentication (public-safe guidance)
- Prefer these auth patterns and do not invent new flows:
1) Interactive user: fab auth login (browser/WAM where supported). 2) Service principal (secret/cert): use environment variables / secure mechanisms; avoid embedding secrets in files. 3) Service principal (federated credential): use the federated token environment variable (FAB_SPN_FEDERATED_TOKEN) and do not persist the raw token. 4) Managed identity: supported for Azure-hosted workloads; no credentials required.
- Never ask users to paste secrets into chat or print them back.
4 - Sensitive data handling (strict)
- Never log or output tokens, passwords, client secrets, or raw federated tokens.
- Validate all user inputs that could affect security:
- Paths: Sanitize file paths and API parameters.
- GUIDs: Validate resource identifiers before use.
- JSON: Validate JSON inputs for proper format.
- If a user shares sensitive strings, advise rotating/regenerating them and moving to secure storage.
5 - Hidden entities and discovery
- Hidden entities are special resources not normally visible, following a dot-prefixed naming convention (similar to UNIX hidden files).
- Tenant-level hidden entities (accessed from root):
.capacities—fab ls .capacities/fab get .capacities/<name>.Capacity.gateways—fab ls .gateways/fab get .gateways/<name>.Gateway.connections—fab ls .connections/fab get .connections/<name>.Connection.domains—fab ls .domains/fab get .domains/<name>.Domain- Workspace-level hidden entities (accessed within a workspace):
.managedidentities—fab ls ws1.Workspace/.managedidentities.managedprivateendpoints—fab ls ws1.Workspace/.managedprivateendpoints.externaldatashares—fab ls ws1.Workspace/.externaldatashares.sparkpools—fab ls ws1.Workspace/.sparkpools- To show hidden resources, recommend
ls -a/ls --all.
6 - Errors and troubleshooting guidance
- When describing failures, include:
- What the command was trying to do
- The likely cause
- The next actionable step
- If the CLI surfaces an error code/message, keep it intact and do not paraphrase away the key identifiers. (Fabric CLI emphasizes stable error codes/messages.)
- Include request IDs for API errors to aid debugging when available.
7 - Output conventions for the agent
- Default to concise, runnable steps.
- When recommending commands, include:
- Preconditions (auth, correct workspace/path)
- Expected result
- How to verify (e.g., follow-up
fab ls/fab get)
8 - Safety defaults
- Ask before suggesting commands that delete, overwrite, or change access/permissions.
- If the user explicitly confirms, proceed with a clear rollback note when possible.
9 - Platform and troubleshooting reference
- Supported platforms: Windows, Linux, macOS.
- Supported shells: zsh, bash, PowerShell, cmd (Windows command prompt).
- Python versions: 3.10, 3.11, 3.12, 3.13.
- CLI file storage (useful for troubleshooting):
- Config files are stored in
~/.config/fab/: cache.bin— encrypted auth token cacheconfig.json— non-sensitive CLI settingsauth.json— non-sensitive auth infocontext-<session_id>— path context for command-line mode sessions- Debug logs are written to:
- Windows:
%AppData%/fabcli_debug.log - macOS:
~/Library/Logs/fabcli_debug.log - Linux:
~/.local/state/fabcli_debug.log
10 - Critical operational rules
- First run: Always run
fab auth statusto verify authentication before executing commands. If not authenticated, ask the user to runfab auth login. - Learn before executing: Always use
fab --helpandfab <command> --helpthe first time you use a command to understand its syntax. - Start simple: Try the basic
fabcommand alone first before piping or chaining. - Non-interactive mode: Use
fabin command-line mode when working with coding agents. Interactive mode doesn't work with automation. - Force flag: Use
-fwhen executing commands if the flag is available to run non-interactively (skips confirmation prompts). - Verify before acting: If workspace or item name is unclear, ask the user first, then verify with
fab lsorfab existsbefore proceeding. - Permission errors: If a command is blocked by permissions, stop and ask the user for clarification; never try to circumvent it.
11 - Common item types
| Extension | Description |
|---|---|
.Workspace | Workspace container |
.Folder | Folder within workspace |
.SemanticModel | Power BI dataset/semantic model |
.Report | Power BI report |
.Dashboard | Power BI dashboard |
.Notebook | Fabric notebook |
.Lakehouse | Lakehouse |
.Warehouse | Data warehouse |
.DataPipeline | Data pipeline |
.SparkJobDefinition | Spark job definition |
.Eventstream | Real-time event stream |
.KQLDatabase | KQL database |
.MLModel | ML model |
.MLExperiment | ML experiment |
.Capacity | Fabric capacity (hidden) |
.Gateway | Data gateway (hidden) |
.Connection | Connection (hidden) |
Use fab desc .<ItemType> to explore any item type.
12 - Command references
For detailed command syntax and working examples, see:
- Quick Start Guide — Copy-paste examples for common tasks
- Full Command Reference — All commands with flags and patterns
- Semantic Models — TMDL, DAX queries, refresh, storage modes
- Notebooks — Job execution, parameters, scheduling
- Reports — Export, import, rebind to models
- Workspaces — Create, manage, permissions
- Querying Data — DAX and lakehouse table queries
- API Reference — Direct REST API access patterns
- Create Workspaces — Workspace creation workflows
fabric-cli-core
Core skill for Microsoft Fabric CLI operations. Load this skill first for any Fabric CLI task.
What This Skill Provides
- Fabric hierarchy mental model (Tenant → Workspace → Folder → Item → OneLakeItem)
- Path conventions with dot entity suffixes (e.g.,
.Workspace,.Notebook) - Authentication patterns (interactive, SPN, managed identity)
- Hidden entity discovery (
ls -a) - Security and sensitive data handling rules
- Critical operational rules
- Common item types reference
Entry Point
Load `SKILL.md` to activate this skill.
References
Detailed documentation in the references/ folder:
| Reference | Description |
|---|---|
| quickstart.md | Copy-paste examples for common tasks |
| reference.md | All commands with flags and patterns |
| semantic-models.md | TMDL, DAX queries, refresh, storage modes |
| notebooks.md | Job execution, parameters, scheduling |
| reports.md | Export, import, rebind to models |
| workspaces.md | Create, manage, permissions |
| querying-data.md | DAX and lakehouse table queries |
| fab-api.md | Direct REST API access patterns |
| create-workspaces.md | Workspace creation workflows |
Creating Workspaces
Create Workspace with Large Storage Format
Step 1: List available capacities
fab ls .capacitiesStep 2: Create workspace on chosen capacity
fab mkdir "Workspace Name.Workspace" -P capacityName="MyCapacity"Step 3: Get workspace ID
fab get "Workspace Name.Workspace" -q "id"Step 4: Set default storage format to Large
fab api -A powerbi -X patch "groups/<workspace-id>" -i '{"defaultDatasetStorageFormat":"Large"}'Done. The workspace now defaults to Large storage format for all new semantic models.
Fabric API Reference
Direct API access via fab api for operations beyond standard commands.
API Basics
# Fabric API (default)
fab api "<endpoint>"
# Power BI API
fab api -A powerbi "<endpoint>"
# With query
fab api "<endpoint>" -q "value[0].id"
# POST with body
fab api -X post "<endpoint>" -i '{"key":"value"}'Capacities
# List all capacities
fab api capacities
# Response includes: id, displayName, sku (F2, F64, FT1, PP3), region, statePause capacity (cost savings):
# CAUTION: Pausing stops all workloads on that capacity
# Resume is intentionally NOT documented - too dangerous for automation
# Use Azure Portal for resume operations
# To pause via Azure CLI (not fab):
az resource update --ids "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Fabric/capacities/{name}" \
--set properties.state=PausedGateways
# List gateways
fab api -A powerbi gateways
# Get gateway datasources
GATEWAY_ID="<gateway-id>"
fab api -A powerbi "gateways/$GATEWAY_ID/datasources"
# Get gateway users
fab api -A powerbi "gateways/$GATEWAY_ID/users"Deployment Pipelines
# List pipelines (user)
fab api -A powerbi pipelines
# List pipelines (admin - all tenant)
fab api -A powerbi admin/pipelines
# Get pipeline stages
PIPELINE_ID="<pipeline-id>"
fab api -A powerbi "pipelines/$PIPELINE_ID/stages"
# Get pipeline operations
fab api -A powerbi "pipelines/$PIPELINE_ID/operations"Deploy content (use Fabric API):
# Assign workspace to stage
fab api -X post "deploymentPipelines/$PIPELINE_ID/stages/$STAGE_ID/assignWorkspace" \
-i '{"workspaceId":"<workspace-id>"}'
# Deploy to next stage
fab api -X post "deploymentPipelines/$PIPELINE_ID/deploy" -i '{
"sourceStageOrder": 0,
"targetStageOrder": 1,
"options": {"allowCreateArtifact": true, "allowOverwriteArtifact": true}
}'Domains
# List domains
fab api admin/domains
# Get domain workspaces
DOMAIN_ID="<domain-id>"
fab api "admin/domains/$DOMAIN_ID/workspaces"
# Assign workspaces to domain
fab api -X post "admin/domains/$DOMAIN_ID/assignWorkspaces" \
-i '{"workspacesIds":["<ws-id-1>","<ws-id-2>"]}'Dataflows
Gen1 (Power BI dataflows):
# List all dataflows (admin)
fab api -A powerbi admin/dataflows
# List workspace dataflows
WS_ID="<workspace-id>"
fab api -A powerbi "groups/$WS_ID/dataflows"
# Refresh dataflow
DATAFLOW_ID="<dataflow-id>"
fab api -A powerbi -X post "groups/$WS_ID/dataflows/$DATAFLOW_ID/refreshes"Gen2 (Fabric dataflows):
# Gen2 dataflows are Fabric items - use standard fab commands
fab ls "ws.Workspace" | grep DataflowGen2
fab get "ws.Workspace/Flow.DataflowGen2" -q "id"Apps
Workspace Apps (published from workspaces):
# List user's apps
fab api -A powerbi apps
# List all apps (admin)
fab api -A powerbi 'admin/apps?$top=100'
# Get app details
APP_ID="<app-id>"
fab api -A powerbi "apps/$APP_ID"
# Get app reports
fab api -A powerbi "apps/$APP_ID/reports"
# Get app dashboards
fab api -A powerbi "apps/$APP_ID/dashboards"Org Apps (template apps from AppSource):
# Org apps are installed from AppSource marketplace
# They appear in the regular apps endpoint after installation
# No separate API for org app catalog - use AppSourceAdmin Operations
Workspaces
# List all workspaces (requires $top)
fab api -A powerbi 'admin/groups?$top=100'
# Response includes: id, name, type, state, capacityId, pipelineId
# Get workspace users
fab api -A powerbi "admin/groups/$WS_ID/users"Items
# List all items in tenant
fab api admin/items
# Response includes: id, type, name, workspaceId, capacityId, creatorPrincipalSecurity Scanning
# Reports shared with entire org (security risk)
fab api -A powerbi "admin/widelySharedArtifacts/linksSharedToWholeOrganization"
# Reports published to web (security risk)
fab api -A powerbi "admin/widelySharedArtifacts/publishedToWeb"Activity Events
# Get activity events (last 30 days max)
# Dates must be in ISO 8601 format with quotes
START="2025-11-26T00:00:00Z"
END="2025-11-27T00:00:00Z"
fab api -A powerbi "admin/activityevents?startDateTime='$START'&endDateTime='$END'"Common Patterns
Extract ID for Chaining
# Get ID and remove quotes
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')
# Use in API call
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'Pagination
# APIs with $top often have pagination
# Check for @odata.nextLink in response
fab api -A powerbi 'admin/groups?$top=100' -q "@odata.nextLink"
# Use returned URL for next pageError Handling
# Check status_code in response
# 200 = success
# 400 = bad request (check parameters)
# 401 = unauthorized (re-authenticate)
# 403 = forbidden (insufficient permissions)
# 404 = not foundAPI Audiences
| Audience | Flag | Base URL | Use Case |
|---|---|---|---|
| Fabric | (default) | api.fabric.microsoft.com | Fabric items, workspaces, admin |
| Power BI | -A powerbi | api.powerbi.com | Reports, datasets, gateways, pipelines |
Most admin operations work with both APIs but return different formats.
Notebook Operations
Comprehensive guide for working with Fabric notebooks using the Fabric CLI.
Overview
Fabric notebooks are interactive documents for data engineering, data science, and analytics. They can be executed, scheduled, and managed via the CLI.
Getting Notebook Information
Basic Notebook Info
# Check if notebook exists
fab exists "Production.Workspace/ETL Pipeline.Notebook"
# Get notebook properties
fab get "Production.Workspace/ETL Pipeline.Notebook"
# Get with verbose details
fab get "Production.Workspace/ETL Pipeline.Notebook" -v
# Get only notebook ID
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "id"Get Notebook Definition
# Get full notebook definition
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition"
# Save definition to file
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition" -o /tmp/notebook-def.json
# Get notebook content (cells)
fab get "Production.Workspace/ETL Pipeline.Notebook" -q "definition.parts[?path=='notebook-content.py'].payload | [0]"Exporting Notebooks
Export as IPYNB
# Export notebook
fab export "Production.Workspace/ETL Pipeline.Notebook" -o /tmp/notebooks
# This creates:
# /tmp/notebooks/ETL Pipeline.Notebook/
# ├── notebook-content.py (or .ipynb)
# └── metadata filesExport All Notebooks from Workspace
# Export all notebooks
WS_ID=$(fab get "Production.Workspace" -q "id")
NOTEBOOKS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='Notebook'].displayName")
for NOTEBOOK in $NOTEBOOKS; do
fab export "Production.Workspace/$NOTEBOOK.Notebook" -o /tmp/notebooks
doneImporting Notebooks
Import from Local
# Import notebook from .ipynb format (default)
fab import "Production.Workspace/New ETL.Notebook" -i /tmp/notebooks/ETL\ Pipeline.Notebook
# Import from .py format
fab import "Production.Workspace/Script.Notebook" -i /tmp/script.py --format pyCopy Between Workspaces
# Copy notebook
fab cp "Dev.Workspace/ETL.Notebook" "Production.Workspace"
# Copy with new name
fab cp "Dev.Workspace/ETL.Notebook" "Production.Workspace/Prod ETL.Notebook"Creating Notebooks
Create Blank Notebook
# Get workspace ID first
fab get "Production.Workspace" -q "id"
# Create via API
fab api -X post "workspaces/<workspace-id>/notebooks" -i '{"displayName": "New Data Processing"}'Create and Configure Query Notebook
Use this workflow to create a notebook for querying lakehouse tables with Spark SQL.
Step 1: Create the notebook
# Get workspace ID
fab get "Sales.Workspace" -q "id"
# Returns: 4caf7825-81ac-4c94-9e46-306b4c20a4d5
# Create notebook
fab api -X post "workspaces/4caf7825-81ac-4c94-9e46-306b4c20a4d5/notebooks" -i '{"displayName": "Data Query"}'
# Returns notebook ID: 97bbd18d-c293-46b8-8536-82fb8bc9bd58Step 2: Get lakehouse ID (required for notebook metadata)
fab get "Sales.Workspace/SalesLH.Lakehouse" -q "id"
# Returns: ddbcc575-805b-4922-84db-ca451b318755Step 3: Create notebook code in Fabric format
cat > /tmp/notebook.py <<'EOF'
# Fabric notebook source
# METADATA ********************
# META {
# META "kernel_info": {
# META "name": "synapse_pyspark"
# META },
# META "dependencies": {
# META "lakehouse": {
# META "default_lakehouse": "ddbcc575-805b-4922-84db-ca451b318755",
# META "default_lakehouse_name": "SalesLH",
# META "default_lakehouse_workspace_id": "4caf7825-81ac-4c94-9e46-306b4c20a4d5"
# META }
# META }
# META }
# CELL ********************
# Query lakehouse table
df = spark.sql("""
SELECT
date_key,
COUNT(*) as num_records
FROM gold.sets
GROUP BY date_key
ORDER BY date_key DESC
LIMIT 10
""")
# IMPORTANT: Convert to pandas and print to capture output
# display(df) will NOT show results via API
pandas_df = df.toPandas()
print(pandas_df)
print(f"\nLatest date: {pandas_df.iloc[0]['date_key']}")
EOFStep 4: Base64 encode and create update definition
base64 -i /tmp/notebook.py > /tmp/notebook-b64.txt
cat > /tmp/update.json <<EOF
{
"definition": {
"parts": [
{
"path": "notebook-content.py",
"payload": "$(cat /tmp/notebook-b64.txt)",
"payloadType": "InlineBase64"
}
]
}
}
EOFStep 5: Update notebook with code
fab api -X post "workspaces/4caf7825-81ac-4c94-9e46-306b4c20a4d5/notebooks/97bbd18d-c293-46b8-8536-82fb8bc9bd58/updateDefinition" -i /tmp/update.json --show_headers
# Returns operation ID in Location headerStep 6: Check update completed
fab api "operations/<operation-id>"
# Wait for status: "Succeeded"Step 7: Run the notebook
fab job start "Sales.Workspace/Data Query.Notebook"
# Returns job instance IDStep 8: Check execution status
fab job run-status "Sales.Workspace/Data Query.Notebook" --id <job-id>
# Wait for status: "Completed"Step 9: Get results (download from Fabric UI)
- Open notebook in Fabric UI after execution
- Print output will be visible in cell outputs
- Download .ipynb file to see printed results locally
Critical Requirements
1. File format: Must be notebook-content.py (NOT .ipynb) 2. Lakehouse ID: Must include default_lakehouse ID in metadata (not just name) 3. Spark session: Will be automatically available when lakehouse is attached 4. Capturing output: Use df.toPandas() and print() - display() won't show in API 5. Results location: Print output visible in UI and downloaded .ipynb, NOT in definition
Common Issues
NameError: name 'spark' is not defined- Lakehouse not attached (missing default_lakehouse ID)- Job "Completed" but no results - Used display() instead of print()
- Update fails - Used .ipynb path instead of .py
Create from Template
# Export template
fab export "Templates.Workspace/Template Notebook.Notebook" -o /tmp/templates
# Import as new notebook
fab import "Production.Workspace/Custom Notebook.Notebook" -i /tmp/templates/Template\ Notebook.NotebookRunning Notebooks
Run Synchronously (Wait for Completion)
# Run notebook and wait
fab job run "Production.Workspace/ETL Pipeline.Notebook"
# Run with timeout (seconds)
fab job run "Production.Workspace/Long Process.Notebook" --timeout 600Run with Parameters
# Run with basic parameters
fab job run "Production.Workspace/ETL Pipeline.Notebook" -P \
date:string=2024-01-01,\
batch_size:int=1000,\
debug_mode:bool=false,\
threshold:float=0.95
# Parameters must match types defined in notebook
# Supported types: string, int, float, boolRun with Spark Configuration
# Run with custom Spark settings
fab job run "Production.Workspace/Big Data Processing.Notebook" -C '{
"conf": {
"spark.executor.memory": "8g",
"spark.executor.cores": "4",
"spark.dynamicAllocation.enabled": "true"
},
"environment": {
"id": "<environment-id>",
"name": "Production Environment"
}
}'
# Run with default lakehouse
fab job run "Production.Workspace/Data Ingestion.Notebook" -C '{
"defaultLakehouse": {
"name": "MainLakehouse",
"id": "<lakehouse-id>",
"workspaceId": "<workspace-id>"
}
}'
# Run with workspace Spark pool
fab job run "Production.Workspace/Analytics.Notebook" -C '{
"useStarterPool": false,
"useWorkspacePool": "HighMemoryPool"
}'Run with Combined Parameters and Configuration
# Combine parameters and configuration
fab job run "Production.Workspace/ETL Pipeline.Notebook" \
-P date:string=2024-01-01,batch:int=500 \
-C '{
"defaultLakehouse": {"name": "StagingLH", "id": "<lakehouse-id>"},
"conf": {"spark.sql.shuffle.partitions": "200"}
}'Run Asynchronously
# Start notebook and return immediately
JOB_ID=$(fab job start "Production.Workspace/ETL Pipeline.Notebook" | grep -o '"id": "[^"]*"' | cut -d'"' -f4)
# Check status later
fab job run-status "Production.Workspace/ETL Pipeline.Notebook" --id "$JOB_ID"Monitoring Notebook Executions
Get Job Status
# Check specific job
fab job run-status "Production.Workspace/ETL Pipeline.Notebook" --id <job-id>
# Get detailed status via API
WS_ID=$(fab get "Production.Workspace" -q "id")
NOTEBOOK_ID=$(fab get "Production.Workspace/ETL Pipeline.Notebook" -q "id")
fab api "workspaces/$WS_ID/items/$NOTEBOOK_ID/jobs/instances/<job-id>"List Execution History
# List all job runs
fab job run-list "Production.Workspace/ETL Pipeline.Notebook"
# List only scheduled runs
fab job run-list "Production.Workspace/ETL Pipeline.Notebook" --schedule
# Get latest run status
fab job run-list "Production.Workspace/ETL Pipeline.Notebook" | head -n 1Cancel Running Job
fab job run-cancel "Production.Workspace/ETL Pipeline.Notebook" --id <job-id>Scheduling Notebooks
Create Cron Schedule
# Run every 30 minutes
fab job run-sch "Production.Workspace/ETL Pipeline.Notebook" \
--type cron \
--interval 30 \
--start 2024-11-15T00:00:00 \
--end 2025-12-31T23:59:00 \
--enableCreate Daily Schedule
# Run daily at 2 AM and 2 PM
fab job run-sch "Production.Workspace/ETL Pipeline.Notebook" \
--type daily \
--interval 02:00,14:00 \
--start 2024-11-15T00:00:00 \
--end 2025-12-31T23:59:00 \
--enableCreate Weekly Schedule
# Run Monday and Friday at 9 AM
fab job run-sch "Production.Workspace/Weekly Report.Notebook" \
--type weekly \
--interval 09:00 \
--days Monday,Friday \
--start 2024-11-15T00:00:00 \
--enableUpdate Schedule
# Modify existing schedule
fab job run-update "Production.Workspace/ETL Pipeline.Notebook" \
--id <schedule-id> \
--type daily \
--interval 03:00 \
--enable
# Disable schedule
fab job run-update "Production.Workspace/ETL Pipeline.Notebook" \
--id <schedule-id> \
--disableNotebook Configuration
Set Default Lakehouse
# Via notebook properties
fab set "Production.Workspace/ETL.Notebook" -q lakehouse -i '{
"known_lakehouses": [{"id": "<lakehouse-id>"}],
"default_lakehouse": "<lakehouse-id>",
"default_lakehouse_name": "MainLakehouse",
"default_lakehouse_workspace_id": "<workspace-id>"
}'Set Default Environment
fab set "Production.Workspace/ETL.Notebook" -q environment -i '{
"environmentId": "<environment-id>",
"workspaceId": "<workspace-id>"
}'Set Default Warehouse
fab set "Production.Workspace/Analytics.Notebook" -q warehouse -i '{
"known_warehouses": [{"id": "<warehouse-id>", "type": "Datawarehouse"}],
"default_warehouse": "<warehouse-id>"
}'Updating Notebooks
Update Display Name
fab set "Production.Workspace/ETL.Notebook" -q displayName -i "ETL Pipeline v2"Update Description
fab set "Production.Workspace/ETL.Notebook" -q description -i "Daily ETL pipeline for sales data ingestion and transformation"Deleting Notebooks
# Delete with confirmation (interactive)
fab rm "Dev.Workspace/Old Notebook.Notebook"
# Force delete without confirmation
fab rm "Dev.Workspace/Old Notebook.Notebook" -fAdvanced Workflows
Parameterized Notebook Execution
# Create parametrized notebook with cell tagged as "parameters"
# In notebook, create cell:
date = "2024-01-01" # default
batch_size = 1000 # default
debug = False # default
# Execute with different parameters
fab job run "Production.Workspace/Parameterized.Notebook" -P \
date:string=2024-02-15,\
batch_size:int=2000,\
debug:bool=trueNotebook Orchestration Pipeline
#!/bin/bash
WORKSPACE="Production.Workspace"
DATE=$(date +%Y-%m-%d)
# 1. Run ingestion notebook
echo "Starting data ingestion..."
fab job run "$WORKSPACE/1_Ingest_Data.Notebook" -P date:string=$DATE
# 2. Run transformation notebook
echo "Running transformations..."
fab job run "$WORKSPACE/2_Transform_Data.Notebook" -P date:string=$DATE
# 3. Run analytics notebook
echo "Generating analytics..."
fab job run "$WORKSPACE/3_Analytics.Notebook" -P date:string=$DATE
# 4. Run reporting notebook
echo "Creating reports..."
fab job run "$WORKSPACE/4_Reports.Notebook" -P date:string=$DATE
echo "Pipeline completed for $DATE"Monitoring Long-Running Notebook
#!/bin/bash
NOTEBOOK="Production.Workspace/Long Process.Notebook"
# Start job
JOB_ID=$(fab job start "$NOTEBOOK" -P date:string=$(date +%Y-%m-%d) | \
grep -o '"id": "[^"]*"' | head -1 | cut -d'"' -f4)
echo "Started job: $JOB_ID"
# Poll status every 30 seconds
while true; do
STATUS=$(fab job run-status "$NOTEBOOK" --id "$JOB_ID" | \
grep -o '"status": "[^"]*"' | cut -d'"' -f4)
echo "[$(date +%H:%M:%S)] Status: $STATUS"
if [[ "$STATUS" == "Completed" ]] || [[ "$STATUS" == "Failed" ]]; then
break
fi
sleep 30
done
if [[ "$STATUS" == "Completed" ]]; then
echo "Job completed successfully"
exit 0
else
echo "Job failed"
exit 1
fiConditional Notebook Execution
#!/bin/bash
WORKSPACE="Production.Workspace"
# Check if data is ready
DATA_READY=$(fab api "workspaces/<ws-id>/lakehouses/<lh-id>/Files/ready.flag" 2>&1 | grep -c "200")
if [ "$DATA_READY" -eq 1 ]; then
echo "Data ready, running notebook..."
fab job run "$WORKSPACE/Process Data.Notebook" -P date:string=$(date +%Y-%m-%d)
else
echo "Data not ready, skipping execution"
fiNotebook Definition Structure
Notebook definition contains:
NotebookName.Notebook/ ├── .platform # Git integration metadata ├── notebook-content.py # Python code (or .ipynb format) └── metadata.json # Notebook metadata
Query Notebook Content
NOTEBOOK="Production.Workspace/ETL.Notebook"
# Get Python code content
fab get "$NOTEBOOK" -q "definition.parts[?path=='notebook-content.py'].payload | [0]" | base64 -d
# Get metadata
fab get "$NOTEBOOK" -q "definition.parts[?path=='metadata.json'].payload | [0]" | base64 -d | jq .Troubleshooting
Notebook Execution Failures
# Check recent execution
fab job run-list "Production.Workspace/ETL.Notebook" | head -n 5
# Get detailed error
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id> -q "error"
# Common issues:
# - Lakehouse not attached
# - Invalid parameters
# - Spark configuration errors
# - Missing dependenciesParameter Type Mismatches
# Parameters must match expected types
# ❌ Wrong: -P count:string=100 (should be int)
# ✅ Right: -P count:int=100
# Check notebook definition for parameter types
fab get "Production.Workspace/ETL.Notebook" -q "definition.parts[?path=='notebook-content.py']"Lakehouse Access Issues
# Verify lakehouse exists and is accessible
fab exists "Production.Workspace/MainLakehouse.Lakehouse"
# Check notebook's lakehouse configuration
fab get "Production.Workspace/ETL.Notebook" -q "properties.lakehouse"
# Re-attach lakehouse
fab set "Production.Workspace/ETL.Notebook" -q lakehouse -i '{
"known_lakehouses": [{"id": "<lakehouse-id>"}],
"default_lakehouse": "<lakehouse-id>",
"default_lakehouse_name": "MainLakehouse",
"default_lakehouse_workspace_id": "<workspace-id>"
}'Performance Tips
1. Use workspace pools: Faster startup than starter pool 2. Cache data in lakehouses: Avoid re-fetching data 3. Parameterize notebooks: Reuse logic with different inputs 4. Monitor execution time: Set appropriate timeouts 5. Use async execution: Don't block on long-running notebooks 6. Optimize Spark config: Tune for specific workloads
Best Practices
1. Tag parameter cells: Use "parameters" tag for injected params 2. Handle failures gracefully: Add error handling and logging 3. Version control notebooks: Export and commit to Git 4. Use descriptive names: Clear naming for scheduled jobs 5. Document parameters: Add comments explaining expected inputs 6. Test locally first: Validate in development workspace 7. Monitor schedules: Review execution history regularly 8. Clean up old notebooks: Remove unused notebooks
Security Considerations
1. Credential management: Use Key Vault for secrets 2. Workspace permissions: Control who can execute notebooks 3. Parameter validation: Sanitize inputs in notebook code 4. Data access: Respect lakehouse/warehouse permissions 5. Logging: Don't log sensitive information
Querying Data
Query a Semantic Model (DAX)
# 1. Get workspace and model IDs
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
MODEL_ID=$(fab get "ws.Workspace/Model.SemanticModel" -q "id" | tr -d '"')
# 2. Execute DAX query
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/executeQueries" \
-X post -i '{"queries":[{"query":"EVALUATE TOPN(10, '\''TableName'\'')"}]}'Query a Lakehouse Table
Lakehouse tables cannot be queried directly via API. Create a Direct Lake semantic model first, then query via DAX.
Get Lakehouse SQL Endpoint
For external SQL clients:
fab get "ws.Workspace/LH.Lakehouse" -q "properties.sqlEndpointProperties"Returns connectionString and id for SQL connections.
Fabric CLI Quick Start Guide
Real working examples using Fabric workspaces and items. These commands are ready to copy-paste and modify for your own workspaces.
Finding Items
List Workspaces
# List all workspaces
fab ls
# List with details (shows IDs, types, etc.)
fab ls -l
# Find specific workspace
fab ls | grep "Sales"List Items in Workspace
# List all items in workspace
fab ls "Sales.Workspace"
# List with details (shows IDs, modification dates)
fab ls "Sales.Workspace" -l
# Filter by type
fab ls "Sales.Workspace" | grep "Notebook"
fab ls "Sales.Workspace" | grep "SemanticModel"
fab ls "Sales.Workspace" | grep "Lakehouse"Check if Item Exists
# Check workspace exists
fab exists "Sales.Workspace"
# Check specific item exists
fab exists "Sales.Workspace/Sales Model.SemanticModel"
fab exists "Sales.Workspace/SalesLH.Lakehouse"
fab exists "Sales.Workspace/ETL - Extract.Notebook"Get Item Details
# Get basic properties
fab get "Sales.Workspace/Sales Model.SemanticModel"
# Get all properties (verbose)
fab get "Sales.Workspace/Sales Model.SemanticModel" -v
# Get specific property (workspace ID)
fab get "Sales.Workspace" -q "id"
# Get specific property (model ID)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Get display name
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "displayName"Working with Semantic Models
Get Model Information
# Get model definition (full TMDL structure)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition"
# Save definition to file
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition" > sales-model-definition.json
# Get model creation date
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "properties.createdDateTime"
# Get model type (DirectLake, Import, etc.)
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "properties.mode"Check Refresh Status
# First, get the workspace ID
fab get "Sales.Workspace" -q "id"
# Returns: a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Then get the model ID
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Returns: 12345678-abcd-ef12-3456-789abcdef012
# Now use those IDs to get latest refresh (put $top in the URL)
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"
# Get full refresh history
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes"Query Model with DAX
# First, get the model definition to see table/column names
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition"
# Get the workspace and model IDs
fab get "Sales.Workspace" -q "id"
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Execute DAX query (using proper table qualification)
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(1, '\''Orders'\'', '\''Orders'\''[OrderDate], DESC)"}],"serializerSettings":{"includeNulls":true}}'
# Query top 5 records from a table
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(5, '\''Orders'\'')"}],"serializerSettings":{"includeNulls":true}}'Trigger Model Refresh
# Get workspace and model IDs
fab get "Sales.Workspace" -q "id"
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Trigger full refresh
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes" -X post -i '{"type": "Full", "commitMode": "Transactional"}'
# Monitor refresh status
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"Working with Notebooks
List Notebooks
# List all notebooks in workspace
fab ls "Sales.Workspace" | grep "Notebook"
# Get specific notebook details
fab get "Sales.Workspace/ETL - Extract.Notebook"
# Get notebook ID
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "id"Run Notebook
# Run notebook synchronously (wait for completion)
fab job run "Sales.Workspace/ETL - Extract.Notebook"
# Run with timeout (300 seconds = 5 minutes)
fab job run "Sales.Workspace/ETL - Extract.Notebook" --timeout 300
# Run with parameters
fab job run "Sales.Workspace/ETL - Extract.Notebook" -P \
date:string=2025-10-17,\
debug:bool=trueRun Notebook Asynchronously
# Start notebook and return immediately
fab job start "Sales.Workspace/ETL - Extract.Notebook"
# Check execution history
fab job run-list "Sales.Workspace/ETL - Extract.Notebook"
# Check specific job status (replace <job-id> with actual ID)
fab job run-status "Sales.Workspace/ETL - Extract.Notebook" --id <job-id>Get Notebook Definition
# Get full notebook definition
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition"
# Save to file
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition" > etl-extract-notebook.json
# Get notebook code content
fab get "Sales.Workspace/ETL - Extract.Notebook" -q "definition.parts[?path=='notebook-content.py'].payload | [0]" | base64 -dWorking with Lakehouses
Browse Lakehouse
# List lakehouse contents
fab ls "Sales.Workspace/SalesLH.Lakehouse"
# List Files directory
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files"
# List specific folder in Files
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files/2025/10"
# List Tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables"
# List with details (shows sizes, modified dates)
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables" -l
# List specific schema tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze"
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold"Get Table Schema
# View table schema
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze/raw_orders"
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders"
# Save schema to file
fab table schema "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders" > orders-schema.jsonCheck Table Last Modified
# List tables with modification times
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold" -l
# Get specific table details
fab get "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders"Working with Reports
List Reports
# List all reports
fab ls "Sales.Workspace" | grep "Report"
# Get report details
fab get "Sales.Workspace/Sales Dashboard.Report"
# Get report ID
fab get "Sales.Workspace/Sales Dashboard.Report" -q "id"Export Report Definition
# Get report definition as JSON
fab get "Sales.Workspace/Sales Dashboard.Report" -q "definition" > sales-report.json
# Export report to local directory (creates PBIR structure)
fab export "Sales.Workspace/Sales Dashboard.Report" -o ./reports-backup -fGet Report Metadata
# Get connected semantic model ID
fab get "Sales.Workspace/Sales Dashboard.Report" -q "properties.datasetId"
# Get report connection string
fab get "Sales.Workspace/Sales Dashboard.Report" -q "definition.parts[?path=='definition.pbir'].payload.datasetReference"Download and Re-upload Workflows
Backup Semantic Model
# 1. Get model definition
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "definition" > backup-sales-model-$(date +%Y%m%d).json
# 2. Get model metadata
fab get "Sales.Workspace/Sales Model.SemanticModel" > backup-sales-model-metadata-$(date +%Y%m%d).jsonExport and Import Notebook
# Export notebook
fab export "Sales.Workspace/ETL - Extract.Notebook" -o ./notebooks-backup
# Import to another workspace (or same workspace with different name)
fab import "Dev.Workspace/ETL Extract Copy.Notebook" -i ./notebooks-backup/ETL\ -\ Extract.NotebookCopy Items Between Workspaces
# Copy semantic model
fab cp "Sales.Workspace/Sales Model.SemanticModel" "Dev.Workspace"
# Copy with new name
fab cp "Sales.Workspace/Sales Model.SemanticModel" "Dev.Workspace/Sales Model Test.SemanticModel"
# Copy notebook
fab cp "Sales.Workspace/ETL - Extract.Notebook" "Dev.Workspace"
# Copy report
fab cp "Sales.Workspace/Sales Dashboard.Report" "Dev.Workspace"Combined Workflows
Complete Model Status Check
# Check last refresh
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes?\$top=1"
# Check latest data in model
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/executeQueries" -X post -i '{"queries":[{"query":"EVALUATE TOPN(1, '\''Orders'\'', '\''Orders'\''[OrderDate], DESC)"}],"serializerSettings":{"includeNulls":true}}'
# Check lakehouse data freshness
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold/orders" -lCheck All Notebooks in Workspace
# List all notebooks
fab ls "Sales.Workspace" | grep Notebook
# Check execution history for each
fab job run-list "Sales.Workspace/ETL - Extract.Notebook"
fab job run-list "Sales.Workspace/ETL - Transform.Notebook"Monitor Lakehouse Data Freshness
# Check gold layer tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/gold" -l
# Check bronze layer tables
fab ls "Sales.Workspace/SalesLH.Lakehouse/Tables/bronze" -l
# Check latest files
fab ls "Sales.Workspace/SalesLH.Lakehouse/Files/2025/10" -lTips and Tricks
Get IDs for API Calls
# Get workspace ID
fab get "Sales.Workspace" -q "id"
# Get model ID
fab get "Sales.Workspace/Sales Model.SemanticModel" -q "id"
# Get lakehouse ID
fab get "Sales.Workspace/SalesLH.Lakehouse" -q "id"
# Then use the IDs directly in API calls
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items"
fab api -A powerbi "groups/a1b2c3d4-e5f6-7890-abcd-ef1234567890/datasets/12345678-abcd-ef12-3456-789abcdef012/refreshes"Pipe to jq for Pretty JSON
# Pretty print JSON output
fab get "Sales.Workspace/Sales Model.SemanticModel" | jq .
# Extract specific fields
fab get "Sales.Workspace/Sales Model.SemanticModel" | jq '{id: .id, name: .displayName, created: .properties.createdDateTime}'
# Get workspace ID first, then filter arrays
fab get "Sales.Workspace" -q "id"
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" | jq '.value[] | select(.type=="Notebook") | .displayName'Use with grep for Filtering
# Find items by pattern
fab ls "Sales.Workspace" | grep -i "etl"
fab ls "Sales.Workspace" | grep -i "sales"
# Count items by type
fab ls "Sales.Workspace" | grep -c "Notebook"
fab ls "Sales.Workspace" | grep -c "SemanticModel"Create Aliases for Common Commands
# Add to ~/.bashrc or ~/.zshrc
alias sales-ls='fab ls "Sales.Workspace"'
alias sales-notebooks='fab ls "Sales.Workspace" | grep Notebook'
alias sales-refresh='fab api -A powerbi "groups/<ws-id>/datasets/<model-id>/refreshes?\$top=1"'
# Then use:
sales-ls
sales-notebooks
sales-refreshCommon Patterns
Get All Items of a Type
# Get workspace ID first
fab get "Sales.Workspace" -q "id"
# Get all notebooks
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Notebook']"
# Get all semantic models
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='SemanticModel']"
# Get all lakehouses
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Lakehouse']"
# Get all reports
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?type=='Report']"Export Entire Workspace
# Export all items in workspace
fab export "Sales.Workspace" -o ./sales-workspace-backup -a
# This creates a full backup with all itemsFind Items by Name Pattern
# Get workspace ID first
fab get "Sales.Workspace" -q "id"
# Find items with "ETL" in name
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?contains(displayName, 'ETL')]"
# Find items with "Sales" in name
fab api "workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/items" -q "value[?contains(displayName, 'Sales')]"Next Steps
- See semantic-models.md for advanced model operations
- See notebooks.md for notebook scheduling and orchestration
- See reports.md for report deployment workflows
Fabric CLI Command Reference
Comprehensive reference for Microsoft Fabric CLI commands, flags, and patterns.
Table of Contents
Item Types
All 35 supported item types:
| Extension | Description |
|---|---|
.Workspace | Workspaces (containers) |
.SemanticModel | Power BI datasets/semantic models |
.Report | Power BI reports |
.Dashboard | Power BI dashboards |
.PaginatedReport | Paginated reports |
.Notebook | Fabric notebooks |
.DataPipeline | Data pipelines |
.SparkJobDefinition | Spark job definitions |
.Lakehouse | Lakehouses |
.Warehouse | Warehouses |
.SQLDatabase | SQL databases |
.SQLEndpoint | SQL endpoints |
.MirroredDatabase | Mirrored databases |
.MirroredWarehouse | Mirrored warehouses |
.KQLDatabase | KQL databases |
.KQLDashboard | KQL dashboards |
.KQLQueryset | KQL querysets |
.Eventhouse | Eventhouses |
.Eventstream | Event streams |
.Datamart | Datamarts |
.Environment | Spark environments |
.Reflex | Reflex items |
.MLModel | ML models |
.MLExperiment | ML experiments |
.GraphQLApi | GraphQL APIs |
.MountedDataFactory | Mounted data factories |
.CopyJob | Copy jobs |
.VariableLibrary | Variable libraries |
.SparkPool | Spark pools |
.ManagedIdentity | Managed identities |
.ManagedPrivateEndpoint | Managed private endpoints |
.ExternalDataShare | External data shares |
.Folder | Folders |
.Capacity | Capacities |
.Personal | Personal workspaces |
File System Commands
ls (dir) - List Resources
Syntax
fab ls [path] [-l] [-a]Flags
-l- Long format (detailed)-a- Show hidden items
Examples
# List workspaces
fab ls
# List items in workspace with details
fab ls "Production.Workspace" -l
# Show hidden items (capacities, connections, domains, gateways)
fab ls -la
# List lakehouse contents
fab ls "Data.Workspace/LH.Lakehouse"
fab ls "Data.Workspace/LH.Lakehouse/Files"
fab ls "Data.Workspace/LH.Lakehouse/Tables/dbo"cd - Change Directory
Syntax
fab cd <path>Examples
# Navigate to workspace
fab cd "Production.Workspace"
# Navigate to item
fab cd "/Analytics.Workspace/Sales.SemanticModel"
# Relative navigation
fab cd "../Dev.Workspace"
# Personal workspace
fab cd ~pwd - Print Working Directory
Syntax
fab pwdexists - Check Existence
Syntax
fab exists <path>Returns
* true or * false
Examples
fab exists "Production.Workspace"
fab exists "Production.Workspace/Sales.SemanticModel"get - Get Resource Details
Syntax
fab get <path> [-v] [-q <jmespath>] [-o <output>]Flags
-v, --verbose- Show all properties-q, --query- JMESPath query-o, --output- Save to file
Examples
# Get workspace
fab get "Production.Workspace"
# Get item with all properties
fab get "Production.Workspace/Sales.Report" -v
# Query specific property
fab get "Production.Workspace" -q "id"
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[0]"
# Save to file
fab get "Production.Workspace/Sales.SemanticModel" -o /tmp/model.jsonset - Set Resource Properties
Syntax
fab set <path> -q <property_path> -i <value>Flags
-q, --query- Property path (JMESPath-style)-i, --input- New value (string or JSON)
Examples
# Update display name
fab set "Production.Workspace/Item.Notebook" -q displayName -i "New Name"
# Update description
fab set "Production.Workspace" -q description -i "Production environment"
# Update Spark runtime
fab set "Production.Workspace" -q sparkSettings.environment.runtimeVersion -i 1.2
# Assign Spark pool
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{"name": "Starter Pool", "type": "Workspace"}'
# Rebind report to model
fab set "Production.Workspace/Report.Report" -q semanticModelId -i "<model-id>"mkdir (create) - Create Resources
Syntax
fab mkdir <path> [-P <param=value>]Flags
-P, --params- Parameters (key=value format)
Examples
# Create workspace
fab mkdir "NewWorkspace.Workspace"
fab mkdir "NewWorkspace.Workspace" -P capacityname=MyCapacity
fab mkdir "NewWorkspace.Workspace" -P capacityname=none
# Create items
fab mkdir "Production.Workspace/NewLakehouse.Lakehouse"
fab mkdir "Production.Workspace/Notebook.Notebook"
# Create with parameters
fab mkdir "Production.Workspace/LH.Lakehouse" -P enableSchemas=true
fab mkdir "Production.Workspace/DW.Warehouse" -P enableCaseInsensitive=true
# Check supported parameters
fab mkdir "Item.Lakehouse" -Pcp (copy) - Copy Resources
Syntax
fab cp <source> <destination>Supported types
.Notebook, .SparkJobDefinition, .DataPipeline, .Report, .SemanticModel, .KQLDatabase, .KQLDashboard, .KQLQueryset, .Eventhouse, .Eventstream, .MirroredDatabase, .Reflex, .MountedDataFactory, .CopyJob, .VariableLibrary
Examples
# Copy item to workspace (keeps same name)
fab cp "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace"
# Copy with new name
fab cp "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace/ProdPipeline.DataPipeline"
# Copy to folder
fab cp "Dev.Workspace/Report.Report" "Production.Workspace/Reports.Folder"
# Copy files to/from lakehouse
fab cp ./local-data.csv "Data.Workspace/LH.Lakehouse/Files/data.csv"
fab cp "Data.Workspace/LH.Lakehouse/Files/data.csv" ~/Downloads/mv (move) - Move Resources
Syntax
fab mv <source> <destination>Examples
# Move item to workspace
fab mv "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace"
# Move with rename
fab mv "Dev.Workspace/Pipeline.DataPipeline" "Production.Workspace/NewPipeline.DataPipeline"
# Move to folder
fab mv "Dev.Workspace/Report.Report" "Production.Workspace/Archive.Folder"rm (del) - Delete Resources
Syntax
fab rm <path> [-f]Flags
-f, --force- Skip confirmation
Examples
# Delete with confirmation (interactive)
fab rm "Dev.Workspace/OldReport.Report"
# Force delete
fab rm "Dev.Workspace/OldLakehouse.Lakehouse" -f
# Delete workspace and all contents
fab rm "OldWorkspace.Workspace" -fexport - Export Item Definitions
Syntax
fab export <item_path> -o <output_path> [-a]Flags
-o, --output- Output directory (local or lakehouse Files)-a- Export all items (when exporting workspace)
Supported types
Same as cp command
Examples
# Export item to local
fab export "Production.Workspace/Sales.SemanticModel" -o /tmp/exports
# Export all workspace items
fab export "Production.Workspace" -o /tmp/backup -a
# Export to lakehouse
fab export "Production.Workspace/Pipeline.DataPipeline" -o "Data.Workspace/Archive.Lakehouse/Files/exports"import - Import Item Definitions
Syntax
fab import <item_path> -i <input_path> [--format <format>]Flags
-i, --input- Input directory or file--format- Format override (e.g.,pyfor notebooks)
Examples
# Import item from local
fab import "Production.Workspace/Pipeline.DataPipeline" -i /tmp/exports/Pipeline.DataPipeline
# Import notebook from Python file
fab import "Production.Workspace/ETL.Notebook" -i /tmp/etl_script.py --format py
# Import from lakehouse
fab import "Production.Workspace/Report.Report" -i "Data.Workspace/Archive.Lakehouse/Files/exports/Report.Report"open - Open in Browser
Syntax
fab open <path>Examples
fab open "Production.Workspace"
fab open "Production.Workspace/Sales.Report"ln (mklink) - Create Shortcuts
Syntax
fab ln <source> <destination>assign / unassign - Capacity Assignment
Syntax
fab assign <workspace> -P capacityId=<capacity-id>
fab unassign <workspace>start / stop - Start/Stop Resources
Syntax
fab start <path> [-f]
fab stop <path> [-f]Supported
.MirroredDatabase
Examples
fab start "Data.Workspace/Mirror.MirroredDatabase" -f
fab stop "Data.Workspace/Mirror.MirroredDatabase" -fAPI Commands
api - Make API Requests
Syntax
fab api <endpoint> [-A <audience>] [-X <method>] [-i <input>] [-q <query>] [-P <params>] [-H <headers>] [--show_headers]Flags
-A, --audience- API audience (fabric, powerbi, storage, azure)-X, --method- HTTP method (get, post, put, delete, patch)-i, --input- Request body (JSON string or file path)-q, --query- JMESPath query to filter response-P, --params- Query parameters (key=value format)-H, --headers- Additional headers (key=value format)--show_headers- Include response headers
Audiences
| Audience | Base URL | Use For |
|---|---|---|
fabric (default) | https://api.fabric.microsoft.com | Fabric REST API |
powerbi | https://api.powerbi.com | Power BI REST API, DAX queries |
storage | https://*.dfs.fabric.microsoft.com | OneLake Storage API |
azure | https://management.azure.com | Azure Resource Manager |
Examples
Fabric API
# GET requests
fab api workspaces
fab api "workspaces/<workspace-id>"
fab api "workspaces/<workspace-id>/items"
fab api workspaces -q "value[?type=='Workspace']"
# POST request with inline JSON
fab api -X post "workspaces/<workspace-id>/items" -i '{"displayName": "New Item", "type": "Lakehouse"}'
# POST with file
fab api -X post "workspaces/<workspace-id>/lakehouses" -i /tmp/config.json
# PUT to update
fab api -X put "workspaces/<workspace-id>/items/<item-id>" -i '{"displayName": "Updated"}'
# DELETE
fab api -X delete "workspaces/<workspace-id>/items/<item-id>"
# Update semantic model definition
fab api -X post "workspaces/<workspace-id>/semanticModels/<model-id>/updateDefinition" -i /tmp/definition.json --show_headersPower BI API
# List groups (workspaces)
fab api -A powerbi groups
# Get datasets in workspace
fab api -A powerbi "groups/<workspace-id>/datasets"
# Execute DAX query
fab api -A powerbi "datasets/<model-id>/executeQueries" -X post -i '{"queries": [{"query": "EVALUATE VALUES(Date[Year])"}]}'
# Refresh dataset
fab api -A powerbi "datasets/<model-id>/refreshes" -X post -i '{}'
# Get refresh history
fab api -A powerbi "datasets/<model-id>/refreshes"OneLake Storage API
# List files with parameters
fab api -A storage "WorkspaceName.Workspace/LH.Lakehouse/Files" -P resource=filesystem,recursive=false
# With query string
fab api -A storage "WorkspaceName/LH.Lakehouse/Files?resource=filesystem&recursive=false"Azure Resource Manager
# List Fabric capacities
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01"
# Get available SKUs
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/skus?api-version=2023-11-01"Job Commands
job run - Run Job Synchronously
Syntax
fab job run <item_path> [--timeout <seconds>] [-P <params>] [-C <config>] [-i <input>]Flags
--timeout- Timeout in seconds-P, --params- Job parameters (typed:name:type=value)-C, --config- Configuration JSON (file or inline)-i, --input- Raw JSON input (file or inline)
Supported items
.Notebook, .DataPipeline, .SparkJobDefinition, .Lakehouse (maintenance)
Parameter types
- Notebook:
string,int,float,bool - DataPipeline:
string,int,float,bool,object,array,secureString
Examples
# Run notebook
fab job run "Production.Workspace/ETL.Notebook"
# Run with timeout
fab job run "Production.Workspace/LongProcess.Notebook" --timeout 300
# Run with parameters
fab job run "Production.Workspace/ETL.Notebook" -P date:string=2024-01-01,batch_size:int=1000,debug:bool=false
# Run pipeline with complex parameters
fab job run "Production.Workspace/Pipeline.DataPipeline" -P 'config:object={"source":"s3","batch":100},ids:array=[1,2,3],secret:secureString=mysecret'
# Run with Spark configuration
fab job run "Production.Workspace/ETL.Notebook" -C '{"conf": {"spark.executor.memory": "8g"}, "environment": {"id": "<env-id>", "name": "ProdEnv"}}'
# Run with default lakehouse
fab job run "Production.Workspace/Process.Notebook" -C '{"defaultLakehouse": {"name": "MainLH", "id": "<lh-id>"}}'
# Run with workspace pool
fab job run "Production.Workspace/BigData.Notebook" -C '{"useStarterPool": false, "useWorkspacePool": "HighMemoryPool"}'
# Run with raw JSON
fab job run "Production.Workspace/ETL.Notebook" -i '{"parameters": {"date": {"type": "string", "value": "2024-01-01"}}, "configuration": {"conf": {"spark.conf1": "value"}}}'job start - Start Job Asynchronously
Syntax
fab job start <item_path> [-P <params>] [-C <config>] [-i <input>]Examples
# Start and return immediately
fab job start "Production.Workspace/ETL.Notebook"
# Start with parameters
fab job start "Production.Workspace/Pipeline.DataPipeline" -P source:string=salesdb,batch:int=500job run-list - List Job History
Syntax
fab job run-list <item_path> [--schedule]Flags
--schedule- Show only scheduled job runs
Examples
# List all job runs
fab job run-list "Production.Workspace/ETL.Notebook"
# List scheduled runs only
fab job run-list "Production.Workspace/ETL.Notebook" --schedulejob run-status - Get Job Status
Syntax
fab job run-status <item_path> --id <job_id> [--schedule]Flags
--id- Job or schedule ID--schedule- Check scheduled job status
Examples
# Check job instance status
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id>
# Check schedule status
fab job run-status "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --schedulejob run-cancel - Cancel Job
Syntax
fab job run-cancel <item_path> --id <job_id>Examples
fab job run-cancel "Production.Workspace/ETL.Notebook" --id <job-id>job run-sch - Schedule Job
Syntax
fab job run-sch <item_path> --type <type> --interval <interval> [--days <days>] --start <datetime> [--end <datetime>] [--enable] [-i <json>]Flags
--type- Schedule type (cron, daily, weekly)--interval- Interval (minutes for cron, HH:MM for daily/weekly)--days- Days for weekly (Monday,Friday)--start- Start datetime (ISO 8601)--end- End datetime (ISO 8601)--enable- Enable schedule immediately-i, --input- Raw JSON schedule configuration
Examples
# Cron schedule (every 10 minutes)
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type cron --interval 10 --start 2024-11-15T09:00:00 --end 2024-12-15T10:00:00 --enable
# Daily schedule
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type daily --interval 10:00,16:00 --start 2024-11-15T09:00:00 --end 2024-12-16T10:00:00
# Weekly schedule
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" --type weekly --interval 10:00,16:00 --days Monday,Friday --start 2024-11-15T09:00:00 --end 2024-12-16T10:00:00 --enable
# Custom JSON configuration
fab job run-sch "Production.Workspace/Pipeline.DataPipeline" -i '{"enabled": true, "configuration": {"startDateTime": "2024-04-28T00:00:00", "endDateTime": "2024-04-30T23:59:00", "localTimeZoneId": "Central Standard Time", "type": "Cron", "interval": 10}}'job run-update - Update Job Schedule
Syntax
fab job run-update <item_path> --id <schedule_id> [--type <type>] [--interval <interval>] [--enable] [--disable] [-i <json>]Examples
# Disable schedule
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --disable
# Update frequency
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> --type cron --interval 5 --enable
# Update with JSON
fab job run-update "Production.Workspace/Pipeline.DataPipeline" --id <schedule-id> -i '{"enabled": false}'Table Commands
table schema - View Table Schema
Syntax
fab table schema <table_path>Supported items
.Lakehouse, .Warehouse, .MirroredDatabase, .SQLDatabase, .SemanticModel, .KQLDatabase
Examples
fab table schema "Data.Workspace/LH.Lakehouse/Tables/dbo/customers"
fab table schema "Analytics.Workspace/DW.Warehouse/Tables/sales/orders"table load - Load Data
Syntax
fab table load <table_path> --file <file_path> [--mode <mode>] [--format <format>] [--extension <ext>]Flags
--file- Source file or folder path (lakehouse Files location)--mode- Load mode (append, overwrite) - default: append--format- Format options (e.g.,format=csv,header=true,delimiter=;)--extension- File extension filter
Note
Not supported in schema-enabled lakehouses.
Examples
# Load CSV from folder
fab table load "Data.Workspace/LH.Lakehouse/Tables/customers" --file "Data.Workspace/LH.Lakehouse/Files/csv/customers"
# Load specific CSV with append mode
fab table load "Data.Workspace/LH.Lakehouse/Tables/sales" --file "Data.Workspace/LH.Lakehouse/Files/daily_sales.csv" --mode append
# Load with custom CSV format
fab table load "Data.Workspace/LH.Lakehouse/Tables/products" --file "Data.Workspace/LH.Lakehouse/Files/data" --format "format=csv,header=false,delimiter=;"
# Load Parquet files
fab table load "Data.Workspace/LH.Lakehouse/Tables/events" --file "Data.Workspace/LH.Lakehouse/Files/parquet/events" --format format=parquet --mode appendtable optimize - Optimize Table
Syntax
fab table optimize <table_path> [--vorder] [--zorder <columns>]Flags
--vorder- Enable V-Order optimization--zorder- Z-Order columns (comma-separated)
Note
Lakehouse only.
Examples
# Basic optimization
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/transactions"
# V-Order optimization
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/sales" --vorder
# V-Order + Z-Order
fab table optimize "Data.Workspace/LH.Lakehouse/Tables/customers" --vorder --zorder customer_id,region_idtable vacuum - Vacuum Table
Syntax
fab table vacuum <table_path> [--retain_n_hours <hours>]Flags
--retain_n_hours- Retention period in hours (default: 168 = 7 days)
Note
Lakehouse only.
Examples
# Vacuum with default retention (7 days)
fab table vacuum "Data.Workspace/LH.Lakehouse/Tables/transactions"
# Vacuum with custom retention (48 hours)
fab table vacuum "Data.Workspace/LH.Lakehouse/Tables/temp_data" --retain_n_hours 48Advanced Patterns
Batch Operations with Shell Scripts
#!/bin/bash
# Export all semantic models from workspace
WORKSPACE="Production.Workspace"
MODELS=$(fab api workspaces -q "value[?displayName=='Production'].id | [0]" | xargs -I {} fab api workspaces/{}/items -q "value[?type=='SemanticModel'].displayName")
for MODEL in $MODELS; do
fab export "$WORKSPACE/$MODEL.SemanticModel" -o /tmp/exports
doneDAX Query Workflow
# 1. Get model ID
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 2. Execute DAX query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE TOPN(10, Sales, Sales[Amount], DESC)"
}],
"serializerSettings": {
"includeNulls": false
}
}'
# 3. Execute multiple queries
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [
{"query": "EVALUATE VALUES(Date[Year])"},
{"query": "EVALUATE SUMMARIZE(Sales, Date[Year], \"Total\", SUM(Sales[Amount]))"}
]
}'Semantic Model Update Workflow
# 1. Get current definition
fab get "Production.Workspace/Sales.SemanticModel" -q definition -o /tmp/current-def.json
# 2. Modify definition (edit JSON file)
# ... edit /tmp/current-def.json ...
# 3. Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 4. Prepare update request (wrap definition)
cat > /tmp/update-request.json <<EOF
{
"definition": $(cat /tmp/current-def.json)
}
EOF
# 5. Update definition
fab api -X post "workspaces/$WS_ID/semanticModels/$MODEL_ID/updateDefinition" -i /tmp/update-request.json --show_headers
# 6. Poll operation status (extract operation ID from Location header)
# Operation ID is in Location header: .../operations/{operation-id}
fab api "operations/<operation-id>"Environment Migration Script
#!/bin/bash
SOURCE_WS="Dev.Workspace"
TARGET_WS="Production.Workspace"
# Export all exportable items
fab export "$SOURCE_WS" -o /tmp/migration -a
# Import items to target workspace
for ITEM in /tmp/migration/*.Notebook; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
done
for ITEM in /tmp/migration/*.DataPipeline; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
doneJob Monitoring Loop
#!/bin/bash
# Start job
JOB_ID=$(fab job start "Production.Workspace/ETL.Notebook" | grep -o '"id": "[^"]*"' | cut -d'"' -f4)
# Poll status every 10 seconds
while true; do
STATUS=$(fab job run-status "Production.Workspace/ETL.Notebook" --id "$JOB_ID" -q "status")
echo "Job status: $STATUS"
if [[ "$STATUS" == "Completed" ]] || [[ "$STATUS" == "Failed" ]]; then
break
fi
sleep 10
done
echo "Job finished with status: $STATUS"Workspace Inventory
#!/bin/bash
# Get all workspaces and their item counts
WORKSPACES=$(fab api workspaces -q "value[].{name: displayName, id: id}")
echo "$WORKSPACES" | jq -r '.[] | [.name, .id] | @tsv' | while IFS=$'\t' read -r NAME ID; do
ITEM_COUNT=$(fab api "workspaces/$ID/items" -q "value | length")
echo "$NAME: $ITEM_COUNT items"
doneJMESPath Quick Reference
Common JMESPath patterns for -q flag:
# Get field
-q "id"
-q "displayName"
# Get nested field
-q "properties.sqlEndpointProperties"
-q "definition.parts[0]"
# Filter array
-q "value[?type=='Lakehouse']"
-q "value[?contains(name, 'prod')]"
-q "value[?starts_with(displayName, 'Test')]"
# Get first/last element
-q "value[0]"
-q "value[-1]"
# Pipe operations
-q "definition.parts[?path=='model.tmdl'] | [0]"
-q "definition.parts[?path=='definition/tables/Sales.tmdl'].payload | [0]"
# Projections (select specific fields)
-q "value[].{name: displayName, id: id, type: type}"
# Length/count
-q "value | length"
# Multi-select list
-q "value[].[displayName, id, type]"
# Flatten
-q "value[].items[]"
# Sort
-q "sort_by(value, &displayName)"
# Boolean logic
-q "value[?type=='Lakehouse' && contains(displayName, 'prod')]"
-q "value[?type=='Lakehouse' || type=='Warehouse']"
# Contains
-q "contains(value[].type, 'Lakehouse')"Common Error Scenarios
Authentication Issues
# 403 Forbidden - Check authentication
fab auth login
# 401 Unauthorized - Token expired, re-authenticate
fab auth login
# Use service principal for automation
fab auth login -u <client-id> -p <client-secret> --tenant <tenant-id>Resource Not Found
# 404 Not Found - Check resource exists
fab exists "Production.Workspace/Sales.SemanticModel"
# List available resources
fab ls "Production.Workspace"
# Get resource ID for API calls
fab get "Production.Workspace/Sales.SemanticModel" -q "id"Job Failures
# Check job status
fab job run-status "Production.Workspace/ETL.Notebook" --id <job-id>
# View job history for patterns
fab job run-list "Production.Workspace/ETL.Notebook"
# Run with timeout to prevent hanging
fab job run "Production.Workspace/ETL.Notebook" --timeout 300API Errors
# 400 Bad Request - Check JSON payload
fab api -X post "workspaces/<ws-id>/items" -i /tmp/payload.json --show_headers
# Debug with headers
fab api workspaces --show_headers
# Save response to inspect
fab api workspaces -o /tmp/debug.jsonPerformance Tips
1. Use `ls` instead of `get` for checking existence - 10-20x faster 2. Use `exists` before `get` operations - Avoids expensive failed gets 3. Filter with JMESPath `-q` - Reduce response size 4. Use GUIDs in automation - More stable than display names 5. Batch exports - Export workspace with -a instead of individual items 6. Parallel job execution - Use job start + polling for multiple jobs 7. Cache workspace/item IDs - Avoid repeated get calls for IDs 8. Use appropriate API audience - Power BI API is faster for dataset queries
Security Best Practices
1. Use service principals for automation - Don't use interactive auth in scripts 2. Store credentials securely - Use environment variables or key vaults 3. Use least-privilege access - Grant minimal required permissions 4. Audit API calls - Log all API operations in production 5. Validate inputs - Sanitize user inputs before passing to API 6. Use force flag carefully - -f skips confirmations, easy to delete wrong resources
Report Operations
Get Report Info
# Check exists
fab exists "ws.Workspace/Report.Report"
# Get properties
fab get "ws.Workspace/Report.Report"
# Get ID
fab get "ws.Workspace/Report.Report" -q "id"Get Report Definition
# Full definition
fab get "ws.Workspace/Report.Report" -q "definition"
# Save to file
fab get "ws.Workspace/Report.Report" -q "definition" -o /tmp/report-def.json
# Specific parts
fab get "ws.Workspace/Report.Report" -q "definition.parts[?path=='definition/report.json'].payload | [0]"Get Connected Model
# Get model reference from definition.pbir
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"Output shows byConnection.connectionString with semanticmodelid.
Export Report
1. Export to local directory:
fab export "ws.Workspace/Report.Report" -o /tmp/exports -f2. Creates structure:
Report.Report/
├── .platform
├── definition.pbir
└── definition/
├── report.json
├── version.json
└── pages/
└── {page-id}/
├── page.json
└── visuals/{visual-id}/visual.jsonImport Report
1. Import from local PBIP:
fab import "ws.Workspace/Report.Report" -i /tmp/exports/Report.Report -f2. Import with new name:
fab import "ws.Workspace/NewName.Report" -i /tmp/exports/Report.Report -fCopy Report Between Workspaces
fab cp "dev.Workspace/Report.Report" "prod.Workspace" -fCreate Blank Report
1. Get model ID:
fab get "ws.Workspace/Model.SemanticModel" -q "id"2. Create report via API:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
fab api -X post "workspaces/$WS_ID/reports" -i '{
"displayName": "New Report",
"datasetId": "<model-id>"
}'Update Report Properties
# Rename
fab set "ws.Workspace/Report.Report" -q displayName -i "New Name"
# Update description
fab set "ws.Workspace/Report.Report" -q description -i "Description text"Rebind to Different Model
1. Get new model ID:
fab get "ws.Workspace/NewModel.SemanticModel" -q "id"2. Rebind:
fab set "ws.Workspace/Report.Report" -q semanticModelId -i "<new-model-id>"Delete Report
fab rm "ws.Workspace/Report.Report" -fList Pages
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'page.json')].path"List Visuals
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, '/visuals/')].path"Count Visuals by Type
1. Export visuals:
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path,'/visuals/')]" > /tmp/visuals.json2. Count by type:
jq -r '.[] | .payload.visual.visualType' < /tmp/visuals.json | sort | uniq -c | sort -rnExtract Fields Used in Report
1. Export visuals (if not done):
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path,'/visuals/')]" > /tmp/visuals.json2. List unique fields:
jq -r '[.[] | (.payload.visual.query.queryState // {} | to_entries[] | .value.projections[]? | if .field.Column then "\(.field.Column.Expression.SourceRef.Entity).\(.field.Column.Property)" elif .field.Measure then "\(.field.Measure.Expression.SourceRef.Entity).\(.field.Measure.Property)" else empty end)] | unique | sort | .[]' < /tmp/visuals.jsonValidate Fields Against Model
1. Export report:
fab export "ws.Workspace/Report.Report" -o /tmp/report -f2. Extract field references:
find /tmp/report -name "visual.json" -exec grep -B2 '"Property":' {} \; | \
grep -E '"Entity":|"Property":' | paste -d' ' - - | \
sed 's/.*"Entity": "\([^"]*\)".*"Property": "\([^"]*\)".*/\1.\2/' | sort -u3. Compare against model definition to find missing fields.
Report Permissions
1. Get IDs:
WS_ID=$(fab get "ws.Workspace" -q "id" | tr -d '"')
REPORT_ID=$(fab get "ws.Workspace/Report.Report" -q "id" | tr -d '"')2. List users:
fab api -A powerbi "groups/$WS_ID/reports/$REPORT_ID/users"3. Add user:
fab api -A powerbi "groups/$WS_ID/reports/$REPORT_ID/users" -X post -i '{
"emailAddress": "user@domain.com",
"reportUserAccessRight": "View"
}'Deploy Report (Dev to Prod)
1. Export from dev:
fab export "dev.Workspace/Report.Report" -o /tmp/deploy -f2. Import to prod:
fab import "prod.Workspace/Report.Report" -i /tmp/deploy/Report.Report -f3. Verify:
fab exists "prod.Workspace/Report.Report"Clone Report with Different Model
1. Export source:
fab export "ws.Workspace/Template.Report" -o /tmp/clone -f2. Edit /tmp/clone/Template.Report/definition.pbir to update semanticmodelid
3. Import as new report:
fab import "ws.Workspace/NewReport.Report" -i /tmp/clone/Template.Report -fTroubleshooting
Report Not Found
fab exists "ws.Workspace"
fab ls "ws.Workspace" | grep -i reportModel Binding Issues
# Check current binding
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"
# Rebind
fab set "ws.Workspace/Report.Report" -q semanticModelId -i "<model-id>"Import Fails
# Verify structure
ls -R /tmp/exports/Report.Report/
# Check definition is valid JSON
fab get "ws.Workspace/Report.Report" -q "definition" | jq . > /dev/null && echo "Valid"Semantic Model Operations
Comprehensive guide for working with semantic models (Power BI datasets) using the Fabric CLI.
Overview
Semantic models in Fabric use TMDL (Tabular Model Definition Language) format for their definitions. This guide covers getting, updating, exporting, and managing semantic models.
Getting Model Information
Basic Model Info
# Check if model exists
fab exists "Production.Workspace/Sales.SemanticModel"
# Get model properties
fab get "Production.Workspace/Sales.SemanticModel"
# Get model with all details (verbose)
fab get "Production.Workspace/Sales.SemanticModel" -v
# Get only model ID
fab get "Production.Workspace/Sales.SemanticModel" -q "id"Get Model Definition
The model definition contains all TMDL parts (tables, measures, relationships, etc.):
# Get full definition (all TMDL parts)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition"
# Save definition to file
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model-def.jsonGet Specific TMDL Parts
# Get model.tmdl (main model properties)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='model.tmdl'].payload | [0]"
# Get specific table definition
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/tables/Customers.tmdl'].payload | [0]"
# Get all table definitions
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?starts_with(path, 'definition/tables/')]"
# Get relationships.tmdl
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/relationships.tmdl'].payload | [0]"
# Get functions.tmdl (DAX functions)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?path=='definition/functions.tmdl'].payload | [0]"
# Get all definition part paths (for reference)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[].path"Exporting Models
Export as PBIP (Power BI Project)
PBIP format is best for local development in Power BI Desktop or Tabular Editor:
# Export model definition
fab export "Production.Workspace/Sales.SemanticModel" -o /tmp/exports -fExport as TMDL
The export creates a folder with TMDL files in the definition folder:
fab export "Production.Workspace/Sales.SemanticModel" -o /tmp/exports -f
# TMDL files will be in: /tmp/exports/Sales.SemanticModel/definition/Export Specific Parts Only
# Export just tables
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?starts_with(path, 'definition/tables/')]" -o /tmp/tables.json
# Export just measures (within tables)
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?contains(path, '/tables/')]" | grep -A 20 "measure"Listing Model Contents
# List all items in model (if OneLake enabled)
fab ls "Production.Workspace/Sales.SemanticModel"
# Query model structure via API
fab api workspaces -q "value[?displayName=='Production'].id | [0]" | xargs -I {} \
fab api "workspaces/{}/items" -q "value[?type=='SemanticModel']"Updating Model Definitions
CRITICAL: When updating semantic models, you must: 1. Get the full definition 2. Modify the specific parts you want to change 3. Include ALL parts in the update request (modified + unmodified) 4. Never include .platform file 5. Test immediately
Update Workflow
# 1. Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# 2. Get current definition
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/current-def.json
# 3. Modify definition (edit JSON file or use script)
# ... modify /tmp/current-def.json ...
# 4. Wrap definition in update request
cat > /tmp/update-request.json <<EOF
{
"definition": $(cat /tmp/current-def.json)
}
EOF
# 5. Update via API
fab api -X post "workspaces/$WS_ID/semanticModels/$MODEL_ID/updateDefinition" \
-i /tmp/update-request.json \
--show_headers
# 6. Extract operation ID from Location header and poll status
OPERATION_ID="<extracted-from-Location-header>"
fab api "operations/$OPERATION_ID"Example: Add a Measure
# Python script to add measure to definition
import json
with open('/tmp/current-def.json', 'r') as f:
definition = json.load(f)
# Find the table's TMDL part
for part in definition['parts']:
if part['path'] == 'definition/tables/Sales.tmdl':
# Decode base64 content
import base64
tmdl_content = base64.b64decode(part['payload']).decode('utf-8')
# Add measure (simplified - real implementation needs proper TMDL syntax)
measure_tmdl = """
measure 'Total Revenue' = SUM(Sales[Amount])
formatString: #,0.00
displayFolder: "KPIs"
"""
tmdl_content += measure_tmdl
# Re-encode
part['payload'] = base64.b64encode(tmdl_content.encode('utf-8')).decode('utf-8')
# Save modified definition
with open('/tmp/modified-def.json', 'w') as f:
json.dump(definition, f)Executing DAX Queries
Use Power BI API to execute DAX queries against semantic models:
# Get model ID
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Execute simple DAX query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE VALUES(Date[Year])"
}]
}'
# Execute TOPN query
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE TOPN(10, Sales, Sales[Amount], DESC)"
}]
}'
# Execute multiple queries
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [
{"query": "EVALUATE VALUES(Date[Year])"},
{"query": "EVALUATE SUMMARIZE(Sales, Date[Year], \"Total\", SUM(Sales[Amount]))"}
],
"serializerSettings": {
"includeNulls": false
}
}'
# Execute query with parameters
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{
"query": "EVALUATE FILTER(Sales, Sales[Year] = @Year)",
"parameters": [
{"name": "@Year", "value": "2024"}
]
}]
}'Refreshing Models
# Get workspace and model IDs
WS_ID=$(fab get "Production.Workspace" -q "id")
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Trigger full refresh
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes" -X post -i '{"type":"Full"}'
# Check latest refresh status
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes?\$top=1"
# Get refresh history
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes"
# Cancel refresh
REFRESH_ID="<refresh-request-id>"
fab api -A powerbi "groups/$WS_ID/datasets/$MODEL_ID/refreshes/$REFRESH_ID" -X deleteModel Refresh Schedule
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
# Get current schedule
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule"
# Update schedule (daily at 2 AM)
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule" -X patch -i '{
"enabled": true,
"days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"times": ["02:00"],
"localTimeZoneId": "UTC"
}'
# Disable schedule
fab api -A powerbi "datasets/$MODEL_ID/refreshSchedule" -X patch -i '{
"enabled": false
}'Copying Models
# Copy semantic model between workspaces (full paths required)
fab cp "Dev.Workspace/Sales.SemanticModel" "Production.Workspace/Sales.SemanticModel" -f
# Copy with new name
fab cp "Dev.Workspace/Sales.SemanticModel" "Production.Workspace/SalesProduction.SemanticModel" -f
# Note: Both source and destination must include workspace.Workspace/model.SemanticModel
# This copies the definition, not data or refreshesModel Deployment Workflow
Dev to Production
#!/bin/bash
DEV_WS="Development.Workspace"
PROD_WS="Production.Workspace"
MODEL_NAME="Sales.SemanticModel"
# 1. Export from dev
fab export "$DEV_WS/$MODEL_NAME" -o /tmp/deployment
# 2. Test locally (optional - requires Power BI Desktop)
# Open /tmp/deployment/Sales/*.pbip in Power BI Desktop
# 3. Import to production
fab import "$PROD_WS/$MODEL_NAME" -i /tmp/deployment/$MODEL_NAME
# 4. Trigger refresh in production
PROD_MODEL_ID=$(fab get "$PROD_WS/$MODEL_NAME" -q "id")
fab api -A powerbi "datasets/$PROD_MODEL_ID/refreshes" -X post -i '{"type": "Full"}'
# 5. Monitor refresh
sleep 10
fab api -A powerbi "datasets/$PROD_MODEL_ID/refreshes" -q "value[0]"Working with Model Metadata
Update Display Name
fab set "Production.Workspace/Sales.SemanticModel" -q displayName -i "Sales Analytics Model"Update Description
fab set "Production.Workspace/Sales.SemanticModel" -q description -i "Primary sales analytics semantic model for production reporting"Advanced Patterns
Extract All Measures
# Get all table definitions containing measures
fab get "Production.Workspace/Sales.SemanticModel" -q "definition.parts[?contains(path, '/tables/')]" -o /tmp/tables.json
# Process with script to extract measures
python3 << 'EOF'
import json
import base64
with open('/tmp/tables.json', 'r') as f:
parts = json.load(f)
measures = []
for part in parts:
if 'tables' in part['path']:
content = base64.b64decode(part['payload']).decode('utf-8')
# Extract measure definitions (simple regex - real parser needed for production)
import re
measure_blocks = re.findall(r'measure\s+[^\n]+\s*=.*?(?=\n\s*(?:measure|column|$))', content, re.DOTALL)
measures.extend(measure_blocks)
for i, measure in enumerate(measures, 1):
print(f"\n--- Measure {i} ---")
print(measure)
EOFCompare Models (Diff)
# Export both models
fab get "Production.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model1-def.json
fab get "Dev.Workspace/Sales.SemanticModel" -q "definition" -o /tmp/model2-def.json
# Use diff tool
diff <(jq -S . /tmp/model1-def.json) <(jq -S . /tmp/model2-def.json)
# jq -S sorts keys for consistent comparisonBackup Model Definition
#!/bin/bash
WORKSPACE="Production.Workspace"
MODEL="Sales.SemanticModel"
BACKUP_DIR="/backups/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
# Export definition
fab export "$WORKSPACE/$MODEL" -o "$BACKUP_DIR" -f
# Save metadata
fab get "$WORKSPACE/$MODEL" -o "$BACKUP_DIR/metadata.json"
echo "Backup completed: $BACKUP_DIR"TMDL Structure Reference
A semantic model's TMDL definition consists of these parts:
model.tmdl # Model properties, culture, compatibility
.platform # Git integration metadata (exclude from updates)
definition/
├── model.tmdl # Alternative location for model properties
├── database.tmdl # Database properties
├── roles.tmdl # Row-level security roles
├── relationships.tmdl # Relationships between tables
├── functions.tmdl # DAX user-defined functions
├── expressions/ # M queries for data sources
│ ├── Source1.tmdl
│ └── Source2.tmdl
└── tables/ # Table definitions
├── Customers.tmdl # Columns, measures, hierarchies
├── Sales.tmdl
├── Products.tmdl
└── Date.tmdlCommon TMDL Parts to Query
MODEL="Production.Workspace/Sales.SemanticModel"
# Model properties
fab get "$MODEL" -q "definition.parts[?path=='model.tmdl'].payload | [0]"
# Roles and RLS
fab get "$MODEL" -q "definition.parts[?path=='definition/roles.tmdl'].payload | [0]"
# Relationships
fab get "$MODEL" -q "definition.parts[?path=='definition/relationships.tmdl'].payload | [0]"
# Data source expressions
fab get "$MODEL" -q "definition.parts[?starts_with(path, 'definition/expressions/')]"
# All tables
fab get "$MODEL" -q "definition.parts[?starts_with(path, 'definition/tables/')].path"Troubleshooting
Model Not Found
# Verify workspace exists
fab exists "Production.Workspace"
# List semantic models in workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel']"Update Definition Fails
Common issues: 1. Included `.platform` file: Never include this in updates 2. Missing parts: Must include ALL parts, not just modified ones 3. Invalid TMDL syntax: Validate TMDL before updating 4. Encoding issues: Ensure base64 encoding is correct
# Debug update operation
fab api "operations/$OPERATION_ID" -q "error"DAX Query Errors
# Check model is online
fab get "Production.Workspace/Sales.SemanticModel" -q "properties"
# Try simple query first
MODEL_ID=$(fab get "Production.Workspace/Sales.SemanticModel" -q "id")
fab api -A powerbi "datasets/$MODEL_ID/executeQueries" -X post -i '{
"queries": [{"query": "EVALUATE {1}"}]
}'Storage Mode
Check table partition mode to determine if model is Direct Lake, Import, or DirectQuery.
# Get table definition and check partition mode
fab get "ws.Workspace/Model.SemanticModel" -q "definition.parts[?contains(path, 'tables/TableName')].payload | [0]"Output shows partition type:
# Direct Lake
partition TableName = entity
mode: directLake
source
entityName: table_name
schemaName: schema
expressionSource: DatabaseQuery
# Import
partition TableName = m
mode: import
source =
let
Source = Sql.Database("connection", "database"),
Data = Source{[Schema="schema",Item="table"]}[Data]
in
DataWorkspace Access
# Get workspace ID
fab get "ws.Workspace" -q "id"
# List users with access
fab api -A powerbi "groups/<workspace-id>/users"Output:
{
"value": [
{
"emailAddress": "user@domain.com",
"groupUserAccessRight": "Admin",
"displayName": "User Name",
"principalType": "User"
}
]
}Access rights: Admin, Member, Contributor, Viewer
Find Reports Using a Model
Check report's definition.pbir for byConnection.semanticmodelid:
# Get model ID
fab get "ws.Workspace/Model.SemanticModel" -q "id"
# Check a report's connection
fab get "ws.Workspace/Report.Report" -q "definition.parts[?contains(path, 'definition.pbir')].payload | [0]"Output:
{
"datasetReference": {
"byConnection": {
"connectionString": "...semanticmodelid=bee906a0-255e-..."
}
}
}To find all reports using a model, check each report's definition.pbir for matching semanticmodelid.
Performance Tips
1. Cache model IDs: Don't repeatedly query for the same ID 2. Use JMESPath filtering: Get only what you need 3. Batch DAX queries: Combine multiple queries in one request 4. Export during off-hours: Large model exports can be slow 5. Use Power BI API for queries: It's optimized for DAX execution
Security Considerations
1. Row-Level Security: Check roles before exposing data 2. Credentials in data sources: Don't commit data source credentials 3. Sensitive measures: Review calculated columns/measures for sensitive logic 4. Export restrictions: Ensure exported models don't contain sensitive data
Workspace Operations
Comprehensive guide for managing Fabric workspaces using the Fabric CLI.
Overview
Workspaces are containers for Fabric items and provide collaboration and security boundaries. This guide covers workspace management, configuration, and operations.
Listing Workspaces
List All Workspaces
# Simple list
fab ls
# Detailed list with metadata
fab ls -l
# List with hidden tenant-level items
fab ls -la
# Hidden items include: capacities, connections, domains, gatewaysFilter Workspaces
# Using API with JMESPath query
fab api workspaces -q "value[].{name: displayName, id: id, type: type}"
# Filter by name pattern
fab api workspaces -q "value[?contains(displayName, 'Production')]"
# Filter by capacity
fab api workspaces -q "value[?capacityId=='<capacity-id>']"
# Get workspace count
fab api workspaces -q "value | length"Getting Workspace Information
Basic Workspace Info
# Check if workspace exists
fab exists "Production.Workspace"
# Get workspace details
fab get "Production.Workspace"
# Get specific property
fab get "Production.Workspace" -q "id"
fab get "Production.Workspace" -q "capacityId"
fab get "Production.Workspace" -q "description"
# Get all properties (verbose)
fab get "Production.Workspace" -v
# Save to file
fab get "Production.Workspace" -o /tmp/workspace-info.jsonGet Workspace Configuration
# Get Spark settings
fab get "Production.Workspace" -q "sparkSettings"
# Get Spark runtime version
fab get "Production.Workspace" -q "sparkSettings.environment.runtimeVersion"
# Get default Spark pool
fab get "Production.Workspace" -q "sparkSettings.pool.defaultPool"Creating Workspaces
Create with Default Capacity
# Use CLI-configured default capacity
fab mkdir "NewWorkspace.Workspace"
# Verify capacity configuration first
fab api workspaces -q "value[0].capacityId"Create with Specific Capacity
# Assign to specific capacity
fab mkdir "Production Workspace.Workspace" -P capacityname=ProductionCapacity
# Get capacity name from capacity list
fab ls -la | grep CapacityCreate without Capacity
# Create in shared capacity (not recommended for production)
fab mkdir "Dev Workspace.Workspace" -P capacityname=noneListing Workspace Contents
List Items in Workspace
# Simple list
fab ls "Production.Workspace"
# Detailed list with metadata
fab ls "Production.Workspace" -l
# Include hidden items (Spark pools, managed identities, etc.)
fab ls "Production.Workspace" -la
# Hidden workspace items include:
# - External Data Shares
# - Managed Identities
# - Managed Private Endpoints
# - Spark PoolsFilter Items by Type
WS_ID=$(fab get "Production.Workspace" -q "id")
# List semantic models only
fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel']"
# List reports only
fab api "workspaces/$WS_ID/items" -q "value[?type=='Report']"
# List notebooks
fab api "workspaces/$WS_ID/items" -q "value[?type=='Notebook']"
# List lakehouses
fab api "workspaces/$WS_ID/items" -q "value[?type=='Lakehouse']"
# Count items by type
fab api "workspaces/$WS_ID/items" -q "value | group_by(@, &type)"Updating Workspaces
Update Display Name
fab set "OldName.Workspace" -q displayName -i "NewName"
# Note: This changes the display name, not the workspace IDUpdate Description
fab set "Production.Workspace" -q description -i "Production environment for enterprise analytics"Configure Spark Settings
# Set Spark runtime version
fab set "Production.Workspace" -q sparkSettings.environment.runtimeVersion -i 1.2
# Set starter pool as default
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{
"name": "Starter Pool",
"type": "Workspace"
}'
# Set custom workspace pool
fab set "Production.Workspace" -q sparkSettings.pool.defaultPool -i '{
"name": "HighMemoryPool",
"type": "Workspace",
"id": "<pool-id>"
}'Capacity Management
Assign Workspace to Capacity
# Get capacity ID
CAPACITY_ID=$(fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01" -q "value[?name=='MyCapacity'].id | [0]")
# Assign workspace
fab assign "Production.Workspace" -P capacityId=$CAPACITY_IDUnassign from Capacity
# Move to shared capacity
fab unassign "Dev.Workspace"List Workspaces by Capacity
# Get all workspaces
fab api workspaces -q "value[] | group_by(@, &capacityId)"
# List workspaces on specific capacity
fab api workspaces -q "value[?capacityId=='<capacity-id>'].displayName"Workspace Migration
Export Entire Workspace
# Export all items
fab export "Production.Workspace" -o /tmp/workspace-backup -a
# This exports all supported item types:
# - Notebooks
# - Data Pipelines
# - Reports
# - Semantic Models
# - etc.Selective Export
#!/bin/bash
WORKSPACE="Production.Workspace"
OUTPUT_DIR="/tmp/migration"
# Export only semantic models
WS_ID=$(fab get "$WORKSPACE" -q "id")
MODELS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='SemanticModel'].displayName")
for MODEL in $MODELS; do
fab export "$WORKSPACE/$MODEL.SemanticModel" -o "$OUTPUT_DIR/models"
done
# Export only reports
REPORTS=$(fab api "workspaces/$WS_ID/items" -q "value[?type=='Report'].displayName")
for REPORT in $REPORTS; do
fab export "$WORKSPACE/$REPORT.Report" -o "$OUTPUT_DIR/reports"
doneCopy Workspace Contents
# Copy all items to another workspace (interactive selection)
fab cp "Source.Workspace" "Target.Workspace"
# Copy specific items
fab cp "Source.Workspace/Model.SemanticModel" "Target.Workspace"
fab cp "Source.Workspace/Report.Report" "Target.Workspace"
fab cp "Source.Workspace/Notebook.Notebook" "Target.Workspace"Deleting Workspaces
Delete with Confirmation
# Interactive confirmation (lists items first)
fab rm "OldWorkspace.Workspace"Force Delete
# Delete workspace and all contents without confirmation
# ⚠️ DANGEROUS - Cannot be undone
fab rm "TestWorkspace.Workspace" -fNavigation
Change to Workspace
# Navigate to workspace
fab cd "Production.Workspace"
# Verify current location
fab pwd
# Navigate to personal workspace
fab cd ~Relative Navigation
# From workspace to another
fab cd "../Dev.Workspace"
# To parent (tenant level)
fab cd ..Workspace Inventory
Get Complete Inventory
#!/bin/bash
WORKSPACE="Production.Workspace"
WS_ID=$(fab get "$WORKSPACE" -q "id")
echo "=== Workspace: $WORKSPACE ==="
echo
# Get all items
ITEMS=$(fab api "workspaces/$WS_ID/items")
# Count by type
echo "Item Counts:"
echo "$ITEMS" | jq -r '.value | group_by(.type) | map({type: .[0].type, count: length}) | .[] | "\(.type): \(.count)"'
echo
echo "Total Items: $(echo "$ITEMS" | jq '.value | length')"
# List items
echo
echo "=== Items ==="
echo "$ITEMS" | jq -r '.value[] | "\(.type): \(.displayName)"' | sortGenerate Inventory Report
#!/bin/bash
OUTPUT_FILE="/tmp/workspace-inventory.csv"
echo "Workspace,Item Type,Item Name,Created Date,Modified Date" > "$OUTPUT_FILE"
# Get all workspaces
WORKSPACES=$(fab api workspaces -q "value[].{name: displayName, id: id}")
echo "$WORKSPACES" | jq -r '.[] | [.name, .id] | @tsv' | while IFS=$'\t' read -r WS_NAME WS_ID; do
# Get items in workspace
ITEMS=$(fab api "workspaces/$WS_ID/items")
echo "$ITEMS" | jq -r --arg ws "$WS_NAME" '.value[] | [$ws, .type, .displayName, .createdDate, .lastModifiedDate] | @csv' >> "$OUTPUT_FILE"
done
echo "Inventory saved to $OUTPUT_FILE"Workspace Permissions
List Workspace Users
WS_ID=$(fab get "Production.Workspace" -q "id")
# List users with access
fab api -A powerbi "groups/$WS_ID/users"Add User to Workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
# Add user as member
fab api -A powerbi "groups/$WS_ID/users" -X post -i '{
"emailAddress": "user@company.com",
"groupUserAccessRight": "Member"
}'
# Access levels: Admin, Member, Contributor, ViewerRemove User from Workspace
WS_ID=$(fab get "Production.Workspace" -q "id")
# Remove user
fab api -A powerbi "groups/$WS_ID/users/user@company.com" -X deleteWorkspace Settings
Git Integration
WS_ID=$(fab get "Production.Workspace" -q "id")
# Get Git connection status
fab api "workspaces/$WS_ID/git/connection"
# Connect to Git (requires Git integration setup)
fab api -X post "workspaces/$WS_ID/git/initializeConnection" -i '{
"gitProviderDetails": {
"organizationName": "myorg",
"projectName": "fabric-project",
"repositoryName": "production",
"branchName": "main",
"directoryName": "/workspace-content"
}
}'Advanced Workflows
Clone Workspace
#!/bin/bash
SOURCE_WS="Template.Workspace"
TARGET_WS="New Project.Workspace"
CAPACITY="MyCapacity"
# 1. Create target workspace
fab mkdir "$TARGET_WS" -P capacityname=$CAPACITY
# 2. Export all items from source
fab export "$SOURCE_WS" -o /tmp/clone -a
# 3. Import items to target
for ITEM in /tmp/clone/*; do
ITEM_NAME=$(basename "$ITEM")
fab import "$TARGET_WS/$ITEM_NAME" -i "$ITEM"
done
echo "Workspace cloned successfully"Workspace Comparison
#!/bin/bash
WS1="Production.Workspace"
WS2="Development.Workspace"
WS1_ID=$(fab get "$WS1" -q "id")
WS2_ID=$(fab get "$WS2" -q "id")
echo "=== Comparing Workspaces ==="
echo
echo "--- $WS1 ---"
fab api "workspaces/$WS1_ID/items" -q "value[].{type: type, name: displayName}" | jq -r '.[] | "\(.type): \(.name)"' | sort > /tmp/ws1.txt
echo "--- $WS2 ---"
fab api "workspaces/$WS2_ID/items" -q "value[].{type: type, name: displayName}" | jq -r '.[] | "\(.type): \(.name)"' | sort > /tmp/ws2.txt
echo
echo "=== Differences ==="
diff /tmp/ws1.txt /tmp/ws2.txt
rm /tmp/ws1.txt /tmp/ws2.txtBatch Workspace Operations
#!/bin/bash
# Update description for all production workspaces
PROD_WORKSPACES=$(fab api workspaces -q "value[?contains(displayName, 'Prod')].displayName")
for WS in $PROD_WORKSPACES; do
echo "Updating $WS..."
fab set "$WS.Workspace" -q description -i "Production environment - managed by Data Platform team"
doneWorkspace Monitoring
Monitor Workspace Activity
WS_ID=$(fab get "Production.Workspace" -q "id")
# Get activity events (requires admin access)
fab api -A powerbi "admin/activityevents?filter=Workspace%20eq%20'$WS_ID'"Track Workspace Size
#!/bin/bash
WORKSPACE="Production.Workspace"
WS_ID=$(fab get "$WORKSPACE" -q "id")
# Count items
ITEM_COUNT=$(fab api "workspaces/$WS_ID/items" -q "value | length")
# Count by type
echo "=== Workspace: $WORKSPACE ==="
echo "Total Items: $ITEM_COUNT"
echo
echo "Items by Type:"
fab api "workspaces/$WS_ID/items" -q "value | group_by(@, &type) | map({type: .[0].type, count: length}) | sort_by(.count) | reverse | .[]" | jq -r '"\(.type): \(.count)"'Troubleshooting
Workspace Not Found
# List all workspaces to verify name
fab ls | grep -i "production"
# Get by ID directly
fab api "workspaces/<workspace-id>"Capacity Issues
# Check workspace capacity assignment
fab get "Production.Workspace" -q "capacityId"
# List available capacities
fab ls -la | grep Capacity
# Verify capacity status (via Azure API)
fab api -A azure "subscriptions/<subscription-id>/providers/Microsoft.Fabric/capacities?api-version=2023-11-01" -q "value[].{name: name, state: properties.state, sku: sku.name}"Permission Errors
# Verify your access level
WS_ID=$(fab get "Production.Workspace" -q "id")
fab api -A powerbi "groups/$WS_ID/users" | grep "$(whoami)"
# Check if you're workspace admin
fab api -A powerbi "groups/$WS_ID/users" -q "value[?emailAddress=='your@email.com'].groupUserAccessRight"Best Practices
1. Naming conventions: Use consistent naming (e.g., "ProjectName - Environment") 2. Capacity planning: Assign workspaces to appropriate capacities 3. Access control: Use least-privilege principle for permissions 4. Git integration: Enable for production workspaces 5. Regular backups: Export critical workspaces periodically 6. Documentation: Maintain workspace descriptions 7. Monitoring: Track workspace activity and growth 8. Cleanup: Remove unused workspaces regularly
Performance Tips
1. Cache workspace IDs: Don't repeatedly query for same ID 2. Use JMESPath filters: Get only needed data 3. Parallel operations: Export multiple items concurrently 4. Batch updates: Group similar operations 5. Off-peak operations: Schedule large migrations during low usage
Security Considerations
1. Access reviews: Regularly audit workspace permissions 2. Sensitive data: Use appropriate security labels 3. Capacity isolation: Separate dev/test/prod workspaces 4. Git secrets: Don't commit credentials in Git-integrated workspaces 5. Audit logging: Enable and monitor activity logs
#!/usr/bin/env python3
"""
health_check.py - Verify CLI installation, auth status, and connectivity
This script performs comprehensive health checks for the Fabric CLI environment:
- Verifies fab CLI is installed and accessible
- Checks authentication status
- Validates workspace connectivity
- Optionally verifies specific workspace access
Usage:
python health_check.py [--workspace WS] [--json]
Exit codes:
0 - All checks passed (healthy)
1 - One or more checks failed (issues found)
"""
import argparse
import json
import subprocess
import sys
from typing import Dict, Any, Optional
def run_fab_command(args: list[str], timeout: int = 30) -> tuple[int, str, str]:
"""Execute a fab CLI command and return exit code, stdout, stderr."""
try:
result = subprocess.run(
["fab"] + args,
capture_output=True,
text=True,
timeout=timeout
)
return result.returncode, result.stdout, result.stderr
except FileNotFoundError:
return -1, "", "fab CLI not found in PATH"
except subprocess.TimeoutExpired:
return -2, "", f"Command timed out after {timeout} seconds"
except Exception as e:
return -3, "", str(e)
def check_cli_installed() -> Dict[str, Any]:
"""Check if fab CLI is installed and accessible."""
check = {
"check": "cli_installed",
"description": "Verify fab CLI is installed and accessible",
"status": "unknown",
"details": {}
}
exit_code, stdout, stderr = run_fab_command(["--version"])
if exit_code == 0:
check["status"] = "pass"
check["details"]["version"] = stdout.strip()
elif exit_code == -1:
check["status"] = "fail"
check["details"]["error"] = "fab CLI not found in PATH. Please install the Fabric CLI."
else:
check["status"] = "fail"
check["details"]["error"] = stderr or "Unable to determine CLI version"
return check
def check_auth_status() -> Dict[str, Any]:
"""Check authentication status with Fabric."""
check = {
"check": "auth_status",
"description": "Verify authentication to Microsoft Fabric",
"status": "unknown",
"details": {}
}
exit_code, stdout, stderr = run_fab_command(["auth", "status"])
if exit_code == 0:
check["status"] = "pass"
# Parse auth status output
lines = stdout.strip().split("\n")
for line in lines:
if ":" in line:
key, value = line.split(":", 1)
check["details"][key.strip().lower().replace(" ", "_")] = value.strip()
else:
check["status"] = "fail"
check["details"]["error"] = stderr.strip() or "Not authenticated. Run 'fab auth login' to authenticate."
return check
def check_workspace_connectivity() -> Dict[str, Any]:
"""Check if we can list at least one workspace."""
check = {
"check": "workspace_connectivity",
"description": "Verify ability to list workspaces",
"status": "unknown",
"details": {}
}
# Try to list workspaces (limit to 1 for quick check)
exit_code, stdout, stderr = run_fab_command(["ls", "/", "-q", "[0].name"])
if exit_code == 0 and stdout.strip():
check["status"] = "pass"
check["details"]["sample_workspace"] = stdout.strip().strip('"')
check["details"]["message"] = "Successfully retrieved workspace list"
elif exit_code == 0:
check["status"] = "warn"
check["details"]["message"] = "No workspaces found. You may not have access to any workspaces."
else:
check["status"] = "fail"
check["details"]["error"] = stderr.strip() or "Unable to list workspaces"
return check
def check_specific_workspace(workspace: str) -> Dict[str, Any]:
"""Check access to a specific workspace."""
check = {
"check": "specific_workspace",
"description": f"Verify access to workspace: {workspace}",
"status": "unknown",
"details": {"workspace": workspace}
}
# Ensure workspace has .Workspace suffix
if not workspace.endswith(".Workspace"):
workspace = f"{workspace}.Workspace"
exit_code, stdout, stderr = run_fab_command(["exists", workspace])
if exit_code == 0:
check["status"] = "pass"
check["details"]["message"] = f"Workspace '{workspace}' is accessible"
else:
check["status"] = "fail"
check["details"]["error"] = stderr.strip() or f"Unable to access workspace '{workspace}'"
return check
def run_health_checks(workspace: Optional[str] = None) -> Dict[str, Any]:
"""Run all health checks and return results."""
results = {
"overall_status": "healthy",
"checks": []
}
# Required checks
cli_check = check_cli_installed()
results["checks"].append(cli_check)
# Only proceed with other checks if CLI is installed
if cli_check["status"] == "pass":
auth_check = check_auth_status()
results["checks"].append(auth_check)
# Only check connectivity if authenticated
if auth_check["status"] == "pass":
connectivity_check = check_workspace_connectivity()
results["checks"].append(connectivity_check)
# Check specific workspace if provided
if workspace:
workspace_check = check_specific_workspace(workspace)
results["checks"].append(workspace_check)
# Determine overall status
statuses = [c["status"] for c in results["checks"]]
if "fail" in statuses:
results["overall_status"] = "unhealthy"
elif "warn" in statuses:
results["overall_status"] = "degraded"
return results
def print_human_readable(results: Dict[str, Any]) -> None:
"""Print results in human-readable format."""
status_symbols = {
"pass": "✓",
"fail": "✗",
"warn": "⚠",
"unknown": "?"
}
print("\n" + "=" * 60)
print("FABRIC CLI HEALTH CHECK")
print("=" * 60)
for check in results["checks"]:
symbol = status_symbols.get(check["status"], "?")
status_color = {
"pass": "",
"fail": "",
"warn": "",
"unknown": ""
}.get(check["status"], "")
print(f"\n{symbol} {check['description']}")
print(f" Status: {check['status'].upper()}")
for key, value in check["details"].items():
print(f" {key}: {value}")
print("\n" + "-" * 60)
overall = results["overall_status"].upper()
print(f"OVERALL STATUS: {overall}")
print("=" * 60 + "\n")
def main():
parser = argparse.ArgumentParser(
description="Verify Fabric CLI installation, authentication, and connectivity",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python health_check.py
python health_check.py --workspace Production
python health_check.py --json
python health_check.py --workspace Production.Workspace --json
"""
)
parser.add_argument(
"--workspace", "-w",
help="Specific workspace to verify access (optional)"
)
parser.add_argument(
"--json", "-j",
action="store_true",
help="Output results in JSON format"
)
args = parser.parse_args()
results = run_health_checks(workspace=args.workspace)
if args.json:
print(json.dumps(results, indent=2))
else:
print_human_readable(results)
# Exit with appropriate code
sys.exit(0 if results["overall_status"] == "healthy" else 1)
if __name__ == "__main__":
main()
Related skills
FAQ
What does fabric-cli-core do?
Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources. Activate when users mention fab, Fabric CLI, or need to automate Fabric ope...
When should I use fabric-cli-core?
Invoke when Use Microsoft Fabric CLI (fab) to manage workspaces, semantic models, reports, notebooks, and Fabric resources. Activate when users mention .
Is fabric-cli-core safe to install?
Review the Security Audits panel on this page before installing in production.