Labsco
microsoft logo

powerbi-report-authoring

✓ Official729

by microsoft · part of microsoft/skills-for-fabric

Create and modify Power BI report files in PBIR/PBIP format using the `powerbi-report-author` and `powerbi-desktop` CLIs. Use when the user wants to: (1) implement an approved report spec or design brief, (2) add or edit pages, visuals, filters, slicers, bookmarks, themes, or formatting, (3) validate PBIR and verify rendering in Power BI Desktop. For open-ended visual design, use `powerbi-report-design` first. For end-to-end requirements and approval workflow, use `powerbi-report-planning` first

🧩 One of 7 skills in the microsoft/skills-for-fabric package — works on its own, and pairs well with its siblings.

This is the playbook your agent receives when the skill activates — you don't need to read it to use the skill, but it's here to audit before installing.

Update Check — ONCE PER SESSION (mandatory) The first time this skill is used in a session, run the check-updates skill before proceeding.

  • GitHub Copilot CLI / VS Code: invoke the check-updates skill.
  • Claude Code / Cowork / Cursor / Windsurf / Codex: compare local vs remote package.json version.
  • Skip if the check was already performed earlier in this session.

CRITICAL NOTES

  1. To find the workspace details (including its ID) from workspace name: list all workspaces and, then, use JMESPath filtering
  2. To find the item details (including its ID) from workspace ID, item type, and item name: list all items of that type in that workspace and, then, use JMESPath filtering

Power BI Report Authoring Skill (PBIR/PBIP Format)

This skill enables reading, editing, and creation of Power BI report definition files in the PBIR (Power BI Report) format used by PBIP (Power BI Project) files.

Must/Prefer/Avoid

MUST

  • Use this skill only for concrete PBIR/PBIP report-file mechanics such as pages, visuals, filters, slicers, navigation, bookmarks, themes, formatting, validation, Desktop reloads, and screenshots.
  • Validate PBIR with powerbi-report-author validate after each logical batch.
  • Use powerbi-desktop reload/screenshot workflows for rendered-output changes.
  • Use CLI capability lookup before writing visual roles, formatting objects, enum values, selectors, or expression encodings.

PREFER

  • Start from an approved Design Brief: or _brief/report-spec.md for greenfield report builds.
  • Route visual-design uncertainty to powerbi-report-design before writing files.
  • For semantic model metadata or model-side changes, use a semantic-model authoring skill, Power BI Modeling MCP, or local TMDL files when available.

AVOID

  • Do not guess PBIR JSON from memory when CLI metadata or reference files are available.
  • Do not use only this skill for open-ended design, report planning, or Fabric report item CRUD; pair it with powerbi-report-design, powerbi-report-planning, or powerbi-report-management.

Topic Files and Examples

Use the user's intent to choose the relevant topic file(s) before editing:

FileWhen to read
authoring.mdAdding/modifying pages, visuals, drillthrough, interactions — includes complete JSON examples
powerbi-desktop.mdLive Desktop verification — powerbi-desktop commands, PID selection, reload, screenshots, errors, troubleshooting
screenshot-review.mdScreenshot review checklist and rendered-output troubleshooting after Desktop screenshot capture
formatting-overview.mdRead first for appearance changes — cascade model, encoding rules, selectors, routing to other formatting files
formatting.mdEditing visual.json appearance — selectors, VCOs, encoding mechanics, background-image routing, cascade
color-strategy.mdChart data point colors — theme dataColors vs dataPoint.defaultColor vs dataPoint.fill with selectors, cross-visual measure-color consistency
conditional-formatting.mdData-driven formatting — color gradients (FillRule), rules-based, icon sets, data bars, web URL, field value
page-formatting.mdEditing page.json appearance — canvas background, wallpaper, page background images
filter-pane.mdFilter pane (outspacePane) and filter card (filterCard) chrome — Applied/Available state styling, pane width, search/checkbox colors
theming.mdCreating or editing theme.json — dataColors, textClasses, visualStyles, style presets, ThemeDataColor reference
re-theming.mdSwitching themes on a report with existing visuals — re-theming workflow (color mapping + bulk sweep), dark mode checklist, dark↔light polarity changes. Pair with theming.md when changing colors on a report with per-visual overrides.
expressions.mdBuilding field references (Column, Measure, Aggregation, Hierarchy) and sort definitions
filters.mdAdding/modifying filters — includes complete JSON examples
slicers.mdRead first when adding/modifying slicers or slicer selections — agent workflow, JSON templates, selection config
cartesian.mdAdding bar, column, line charts — families, roles, query patterns (multi-measure, drill hierarchy, date hierarchy), formatting
map.mdAdding map visuals — template, roles, geocoding workflow, handling render failures
card.mdAdding or formatting KPI/card visuals — cardVisual, id selectors, callout/value sizing, accent bars
table.mdAdding or formatting tables/matrices — tableEx, pivotTable, grow-to-fit columns, row banding
image.mdAdding image visuals — local resources, URLs, data-bound images, ImageUrl validation/refusal workflow; also plot area background images for chart visuals
shape.mdAdding shape visuals — containers, dividers, backgrounds, reference-image matching
textbox.mdAdding static or dynamic textbox visuals — paragraphs, text runs, and bound value expressions
version-control.mdGit branching, committing, reverting — read when the task involves version control or safe rollback planning

Greenfield / Design Handoff

This skill owns PBIR file mechanics once the work is concrete: page/visual JSON, bindings, filters, slicers, themes, formatting, navigation, bookmarks, validation, Desktop reloads, and screenshots.

Use powerbi-report-planning before authoring for new report/dashboard requests, requirements gathering, dependency checks, approval, or end-to-end build sequencing. Use powerbi-report-design for open-ended visual design, redesign/restyle, brand/theme direction, chart selection, or layout critique. Return here once there is an approved spec/design brief or a concrete PBIR edit to implement — see Quick Start step 0 for how to consume the brief.

Large Build Execution

For full report/PBIP builds, do not delegate complete PBIP generation to a subagent — the owning agent must keep the design brief, model inventory, cross-page consistency, validation loop, and Desktop verification coordinated.

When context or repetition is the constraint, prefer a deterministic Node.js generator that reads the approved design brief and writes PBIR JSON. If delegation is still useful, split it by page or visual family and give each subagent the relevant brief excerpt, exact fields/measures, and layout/visual contract; have it return scoped PBIR JSON or a patch for the owning agent to integrate and validate.

PBIR File Layout

A PBIP project on disk looks like this:

<Report>.pbip                              # Project manifest
├── <Report>.Report/
│   ├── .platform                          # Fabric metadata (type, logicalId)
│   ├── definition.pbir                    # Report → SemanticModel binding
│   ├── definition/
│   │   ├── version.json                   # Format version (e.g. "2.0.0")
│   │   ├── report.json                    # Report-level: themes, settings, resources
│   │   └── pages/
│   │       ├── pages.json                 # Page order + active page name
│   │       └── <pageId>/
│   │           ├── page.json              # Page: displayName, size, type, filters
│   │           └── visuals/
│   │               └── <visualId>/
│   │                   └── visual.json    # Visual: type, position, query, formatting
│   ├── CustomVisuals/                     # Third-party .pbiviz packages
│   └── StaticResources/
│       ├── SharedResources/BaseThemes/    # Built-in base themes
│       └── RegisteredResources/           # User images, custom theme JSON
└── <Report>.SemanticModel/                # OUT OF SCOPE

Key Files

FilePurposeAgent rule
definition.pbirReport → semantic model binding via byPath or byConnectionPreserve schema/version unless intentionally migrating
version.jsonPBIR format metadataDo not invent values; copy from an existing/scaffolded report
report.jsonReport-level settings, themes, resourcesEdit through references and validate after changes
pages.jsonPage order and active pageAdd every new page to pageOrder
page.jsonPage metadata, size, filtersPreserve dimensions unless resizing is approved
visual.jsonVisual type, position, query, formattingValidate roles and formatting with CLI metadata
localSettings.jsonUser-local settingsDo not commit or rely on it

Schema URLs use the prefix developer.microsoft.com/json-schemas/fabric/item/report/definition/. The suffixes are versioned PBIR contracts that Power BI Desktop bumps with most releases (e.g. visualContainer/2.9.0, page/2.1.0, report/3.3.0 at the time of writing — newer values may appear in any user's PBIP). When editing, always preserve the existing $schema value; when adding a new file, copy the $schema URL from an existing file of the same type in the same report. Do not invent or bump versions on your own. Validate with powerbi-report-author validate.


Authoring Metadata & Validation CLI

Use powerbi-report-author whenever you need PBIR facts that should not be guessed: visual types, data roles, formatting objects, property names, enum values, selectors, expression/value encodings, and report validation. The CLI is the source of truth for PBIR authoring details; examples and memory are not.

CommandPurposeWhen to use
catalog listList all built-in visual types (and any deprecated entries)Choosing a visual type
catalog describe <type>Roles, formatting keys, cardinalityBefore creating/editing a visual
formatting list-objects <type>Valid objects.* keys + VCO keys; flags objects needing id selectorsBefore applying formatting
formatting describe-object <type> <object>Property names, types, enum values, descriptions; _selectorHint when id selector requiredFinding exact property names and allowed values
formatting describe-property <type> <object> <prop>Focused single-property lookupWhen you already know the object and want just one property
formatting search <type> <regex>Regex search across all formatting objects + VCOsWhen you don't know which object a property belongs to
formatting list-vcosEnumerate shared visualContainerObjectsAuditing chrome/container formatting surface
validate <path>Full validation of a .pbip or .Report directory: JSON Schema, structure, IDs, formatting properties, enum values, nesting, layout bounds, themeAfter every batch of changes
preview-* <path> [--with-derived]Report inventory: preview-visuals, preview-pages, preview-filters, preview-themesAuditing existing report content
--help / <command> --helpCommand syntax and available optionsBefore using an unfamiliar command or flag

More commands: powerbi-report-author-cli.md.

Validation result handling

Run powerbi-report-author validate <path-to-.Report-dir> after every logical batch of PBIR edits.

  • failed / non-zero exit: fix every error before Desktop reload. Desktop may reject or misrender invalid PBIR.
  • succeededWithWarnings: review warnings before proceeding. Unknown visual types or theme visual keys usually mean a typo unless the report intentionally uses a custom .pbiviz.
  • Diagnostics include file paths and JSON paths. Use them to jump directly to the broken node.
  • For large diagnostics, use --pretty for readable output or --out <file> to write the full result to a file.

Visual Capability Guardrails

Use these as pre-edit safety rails. Always confirm exact roles, formatting objects, properties, enum values, and selectors with powerbi-report-author before editing.

Prefer modern visual types

Never create legacy visual types. If repairing an existing legacy visual, migrate to the modern type and rebuild roles/formatting from CLI metadata.

Do not createUse instead
cardcardVisual
tabletableEx
matrixpivotTable
map, filledMapazureMap

Instance Selectors

Some formatting objects need { id: ... } selectors. Run formatting list-objects and formatting describe-object; follow _selectorHint and the dual-entry pattern in references/formatting.md.

Edit → Validate → Reload → Screenshot Loop

For rendered-output changes, follow this loop. Do not report completion until validation, reload, and screenshot review are clean.

┌──────────────────────────────────────────────────────────┐
│  1. Edit PBIR files                                      │
│  2. Validate           → errors? fix and go to 1         │
│  3. Desktop status     → choose the correct bridge PID   │
│  4. Desktop reload     → error? fix PBIR and go to 1     │
│  5. Screenshot/review  → issues? fix and go to 1         │
│  6. Clean              → report completion               │
└──────────────────────────────────────────────────────────┘

Rules:

  • Step 2powerbi-report-author validate <path-to-.Report-dir>. Pass the report definition directory (e.g., Sales.Report), not the .pbip file or project root. Fix all errors before reload — invalid PBIR errors will surface in Desktop.
  • Steps 3–5 — use powerbi-desktop CLI: status to choose the PID, then reload --pid <pid> for PBIP/PBIR current files and screenshots from the same PID. Then perform the screenshot review below. reload covers report/PBIR changes only. For semantic-model/TMDL changes, use a semantic-model skill or Modeling MCP and reopen the PBIP if changes are not reflected. Exception: Theme JSON files are cache-keyed by name — Desktop may not pick up edits on reload. Either rename the theme file with a random suffix (and update report.json), or close and reopen Desktop.

Desktop CLI commands:

CommandPurposeWhen to use
open "<path.pbip>"Launch Power BI Desktop for a PBIP/PBIXStarting Desktop or opening the target report
statusList Desktop Bridge instances, current files, report dirs, and bridge stateBefore reload/screenshot; choose the correct PID
reload --pid <pid>Reload the selected Desktop instance's current PBIP report filesAfter validated PBIR edits in an open PBIP
screenshot <page-id> --pid <pid> --output <file>Capture one page by PBIR page IDIsolated page changes
screenshot-all --pid <pid> --output-dir <dir>Capture every report pageTheme, navigation, page-order, or report-wide changes

Use powerbi-desktop screenshot <page-id> --pid <pid> when only one PBIR page needs review. reload is supported only for PBIP-backed reports. No powerbi-desktop command accepts --report; use status to select the Desktop instance by PID because the same PBIP can be open in more than one process. Screenshots default to scale 2. Run reload and screenshot operations serially per PID — never in parallel against the same PID, even as a workaround for a slow or retryable error. Read references/powerbi-desktop.md for the complete command reference and troubleshooting workflow.

Common Desktop CLI outcomes:

Output/errorMeaningAction
"status": "not_connected"No Desktop Bridge discoverableRun powerbi-desktop open "<path.pbip>" or ask the user to start Desktop. If still unreachable, ask them to enable the Desktop preview feature — see docs
AMBIGUOUS_DESKTOP_INSTANCEMore than one Desktop Bridge instance is availableRun powerbi-desktop status, choose the intended PID, retry with --pid
METHOD_NOT_AVAILABLEDesktop build lacks a required production bridge methodTell the user Desktop is stale/unsupported — see docs
HostNotReady / retryable bridge errorDesktop is up but the report host isn't ready (often briefly after a reload)CLI auto-retries; rerun once if it surfaces. Do not add custom sleeps — rely on the CLI's retry path.
Timeout (bridge error)A reload or screenshot exceeded the CLI's retry budgetConfirm status shows bridgeStatus: "connected", then rerun once. If Timeout persists, raise the budget (e.g., reload --pid <pid> --wait-seconds 120). If bridgeStatus: "error" or status hangs, ask the user whether a Desktop modal dialog is blocking input.
Cancelled during screenshot/reloadA reload/screenshot was cancelled — usually a concurrent reload/screenshot on the same PID. Distinct from Timeout (operation ran too long).Run reload and screenshot serially per PID. Wait for connected via status, retry one at a time.
ReportDefinitionValidationFailedDesktop rejected the PBIR definitionFix PBIR, run powerbi-report-author validate <path>, then reload again
REPORT_DIR_REQUIREDSelected PID has no PBIP/PBIR current file; reload/screenshot-all need PBIP/PBIR stateSelect the correct PID from status or open the target PBIP

Screenshot Review

After taking screenshots, perform an independent rendered-output review before reporting completion. Read screenshot-review.md, check layout, data rendering, formatting/theme, slicers, and common screenshot failure modes, then fix PBIR and repeat the loop until clean.


Validation

Run powerbi-report-author validate <path> after every logical batch of PBIR changes. Prefer the .Report directory; the CLI also accepts a .pbip file or a project root containing a single .Report directory. Errors block Desktop reload — fix them first. Review warnings and fix unless there's a clear reason not to.

The validator is an offline preflight covering PBIR structure, JSON/schema validity, cross-file references, IDs/names, visual types, role bindings, filters, formatting objects/properties/enums/selectors, visualContainerObjects, theme registration, layout bounds, and selected Desktop/rendering failure patterns. It does not replace Desktop reload and screenshot review.


Anti-Patterns and Pitfalls

PitfallConsequenceFix
Using "Entity" inside filter Where conditionsFilter silently failsUse "Source" with the alias from From
Omitting nativeQueryRefVisual calculations may breakAlways include nativeQueryRef
Reusing visual/filter namesUnpredictable behaviorGenerate unique IDs
Setting visualType to invalid stringVisual renders as error boxRun powerbi-report-author catalog describe <type> or powerbi-report-author catalog list
Wrong role name for visual typeField is ignored; visual blankMatch role names from powerbi-report-author catalog describe <type>
Mixing Column and Measure typesQuery fails; visual errorColumns use Column, measures use Measure
Forgetting to add page to pages.jsonPage invisibleAdd to pageOrder array
Booleans without correct formatWrong type"true" / "false" (no suffix, unquoted in Value)
Numbers without type suffixType mismatchD for decimals, L for integers
Editing $schema versionPBI Desktop may rejectPreserve existing version
Stringified JSON in paragraphsTextbox shows nothingparagraphs is a native JSON array
Using textbox as a thin line/dividerRenders ~24px tall regardless of heightUse a shape visual (rectangle) instead — shapes respect small dimensions
visualContainerObjects as sibling of visualSchema validation error in PBI DesktopMust be inside visual object, as sibling of objects
Using tableEx with dimension columns and measures all in ValuesHeaders render but no data rows even when DAX confirms data existsUse pivotTable; put dimensions in Rows and measures in Values
Using PowerShell ConvertTo-Json to edit visual JSONProperty reordering, nesting depth truncation (-Depth default is 2)Use Node.js for JSON manipulation, or always pass -Depth 20 and verify structure
Using regex or string replacement to modify JSON filesCorrupts nesting structure — properties end up inside sibling values, braces misalignRead file → JSON.parse → modify object → JSON.stringify → write back. Or use the edit tool with exact old/new string matching
dataPoint.fill without a selector on single-series chartsBars/columns invisible despite data in tooltipsUse dataPoint.defaultColor for unselectored base color; fill requires a metadata selector
Using dataPoint.defaultColor on multi-series chartsAll series/categories get the same color — no visual differentiationUse theme dataColors for consistent palette across visuals, or dataPoint.fill with metadata selectors for per-series overrides — see color-strategy.md § Color Strategy Quick Reference
Clustered bar/column chart colors collapse into one legend colorThe visual has a Series role but all bars and legend markers share the same hueUse per-series dataPoint.fill selectors or a theme dataColors palette; do not use defaultColor on clustered charts
Relying on theme dataColors alone for cross-visual measure consistencySame measure gets different colors on different visuals (index-based assignment varies with projection order)Maintain a measure→color mapping and apply explicit dataPoint.fill/defaultColor per visual — see color-strategy.md § Cross-Visual Measure-Color Consistency
Using ThemeDataColor for explicit per-measure dataPoint.fill with metadata selectorsColors silently resolve to white or black instead of expected palette colorUse Literal hex values for explicit color assignments with metadata selectors — ThemeDataColor is unreliable in this context
Choosing bar/series colors without checking background contrastBars or lines invisible against page/card background (e.g., white bars on white canvas)Always pick saturated, mid-to-dark hues that contrast with the page and VCO background colors
show property on page-level backgroundSchema error — page background only supports color, image, transparencyOnly VCO background (on visuals) has show; page background is always visible
Copying property names from doc examples without verifyingWarnings or silent failures — property names vary by visual typeAlways run powerbi-report-author formatting describe-object <type> <object> for exact property names
Guessing which object a property belongs toWasted calls checking wrong objects one by oneRun powerbi-report-author formatting search <type> <regex> to grep across all objects at once
Formatting property has no effect (no error)Setting show: false on cardVisual outline without an id selector — validates but renders unchangedCheck powerbi-report-author formatting describe-object <type> <object> for _selectorHint; use the dual-entry pattern (static + id selector entries)
Using cardCalloutArea on a single-value cardProperties validate but have no visible effect — cardCalloutArea only renders on multi-value cards (2+ measures in Data)Use outline/accentBar/fillCustom with { id: "default" } selector for single-value cards. For multi-value cards, cardCalloutArea controls per-callout tile styling — see card.md § Multi-Value Formatting
Adding multiple fields to button slicer Values or Label rolesSlicer breaks or shows unexpected results — each role accepts only 1 fieldPut one field in Values, one in Label; additional fields go to Tooltips
Looking at filterConfig on other visuals to understand slicer selectionsSlicer selections live only inside the slicer's own visual.json via expansionStates + objects.general.filter. Always read references/slicers.md first when modifying slicers
Creating an image visual without prompting for the source typeWrong visual structure — URL vs local file vs data field each have different schemas and expression typesAlways ask the user for the image source (local file / URL / data field) before creating the visual — see image.md § Source Types Overview
Creating a data-bound image visual with a field that lacks dataCategory: ImageUrlVisual renders blank or errorWarn the user first — the visual will render blank without dataCategory: ImageUrl. Present alternatives (other ImageUrl fields, local file, URL) and confirm before creating — see image.md § Select from data
Placing background image on page canvas instead of visual plot areaUser asks for "background image" alongside a visual (e.g., "column chart with background image") but image is placed on page.json → objects.background instead of visual.objects.plotAreaWhen a background image is requested in the context of a specific visual, default to plotArea.image. Only use page-level background.image when the user explicitly says "page background" / "canvas background" or no visual context exists — see image.md § Plot Area Background Image
Using map or filledMap instead of azureMap for map visualsLegacy Bing Maps visuals — deprecated and must not be created; powerbi-report-author validate warns with PBIR_VISUAL_TYPE_DEPRECATEDAlways use azureMap — see map.md. If the map fails to render or geocode, debug the fields, try alternative geographic columns/coordinates, or ask the user — do not silently substitute a non-map visual without consulting the user first
Creating tableEx/pivotTable without columnAdjustment: growToFitColumns shrink-wrap to content, leaving unused whitespaceAlways set columnHeaders.columnAdjustment to growToFit and autoSizeColumnWidth to true — see table.md
Custom table/matrix row colors with no effect (white background)Default style preset overrides objects-level backColorPrimary/backColorSecondarySet stylePreset VCO to 'None' on every tableEx/pivotTable with custom colors — see table.md § Style Presets
Table cells white despite dark VCO backgroundvisualContainerObjects.background only controls outer container — table cells paint on topSet dark colors in objects.values.backColorPrimary/Secondary and objects.columnHeaders.backColor, not in VCO — see re-theming.md § Dark Mode Checklist
Dark theme applied but cards/tables/slicers still whiteDark mode triggers every formatting trap simultaneouslyFollow the full re-theming.md § Dark Mode Authoring Checklist — covers stylePreset, fillCustom+id selector, objects vs VCO, and contrast audit
Theme JSON changes do not appear after Desktop reloadDesktop caches theme files by file nameRename the theme JSON with a small random suffix, update the theme registration in report.json, then reload; otherwise close and reopen Desktop
Placing sortDefinition inside visual or at root of visual.jsonSchema validation error; sort silently ignored — chart falls back to alphabeticalsortDefinition is a property of query — use visual.query.sortDefinition. Supported since visualConfiguration/2.2.0
Container shape fill doesn't match referenceText invisible or wrong background colorMatch the fill color and transparency to the reference image. If the page background already provides the color, skip the shape entirely. If the shape must be invisible, verify text color still contrasts with the page canvas — see shape.md § Container Shapes
Shape text invisible after re-themeShape text object has no explicit fontColor — text inherits theme foreground, but when fill is a light color (e.g., white pill/button) on a light page canvas, inherited dark foreground may not render or the fill blends with canvas making text vanishAlways set explicit fontColor on shape text objects (in the { selector: { id: "default" } } entry). During re-theming, audit all shapes with text.show: true — bulk hex-replacement misses shapes that need a new fontColor property added
Enabling logAxisScale on data with zero or negative valuesPBI Desktop silently falls back to linear scale with a warning — log of zero/negative is undefinedWarn the user before applying. Use ask_user to present alternatives (filter negatives, switch measure, use labelDisplayUnits). Apply logAxisScale: true only after the user resolves negative values or confirms all bound values are positive — see cartesian.md § Log Scale
Changing theme without sweeping inline overridesOld colors remain on shapes, page backgrounds, nav buttons, textboxes — theme-only change has no effect on hardcoded Literal hex values at Priority 2 in the cascadeWhen the report has per-visual color overrides, follow re-theming.md § Re-theming Workflow Steps 0–3: build a color mapping, update theme JSON, then bulk-sweep definition/ files for old hex values before reload
Changing only dataColors in theme without sweepingShapes, accent bars, nav button borders retain old accent colors — they use hardcoded Literal hex from the old dataColors array, not ThemeDataColor referencesSweep ALL old dataColors[N] hex values across definition/ files. Even same-polarity "just change the accent/data colors" requests need the full sweep — shapes and nav elements commonly hardcode dataColors[0] as accent fills/outlines.

Official Documentation

For Microsoft Learn setup guidance, support constraints, and feature availability, use Power BI report authoring docs.