Skip to main content
ClaudeWave
Skill693 repo starsupdated today

tmdl

The tmdl skill provides direct editing guidance for TMDL files in Power BI IP projects when specialized tools like Tabular Editor CLI or the Power BI MCP server are unavailable. It covers measure and column authoring, description management, DAX syntax formatting, and indentation rules specific to TMDL's whitespace-sensitive structure, and should be invoked for text-level fixes in Git-based workflows where full validation tools are impractical.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/data-goblin/power-bi-agentic-development /tmp/tmdl && cp -r /tmp/tmdl/plugins/pbip/skills/tmdl ~/.claude/skills/tmdl
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# TMDL Authoring

Expert guidance for authoring and editing TMDL (Tabular Model Definition Language) files directly in PBIP projects.

> **This skill is a last resort.** Direct TMDL file editing lacks the validation, atomicity, and DAX query capabilities of the Tabular Editor CLI, Power BI MCP server, or the `connect-pbid` skill (TOM via PowerShell). Use those tools when available. TMDL editing is appropriate when:
>
> - Working with PBIP files in a Git repo without Power BI Desktop open
> - No Tabular Editor CLI or MCP server is installed
> - Making quick text-level fixes (descriptions, format strings, display folders) where a full tool chain is overkill
>
> Direct TMDL editing does not validate DAX syntax, check referential integrity, or verify that property values are valid. Errors will only surface when the model is next loaded in Power BI Desktop or deployed via XMLA. Use the **`pbip-validator`** agent to check TMDL files for syntax issues, indentation errors, and referential integrity before opening in PBI Desktop.

## When to Use This Skill

Activate only when the Tabular Editor CLI, Power BI MCP server, or `connect-pbid` skill are not available, and tasks involve:

- Editing `.tmdl` files directly (measures, columns, tables, relationships)
- Adding or modifying measure definitions in TMDL
- Adding descriptions to columns, measures, or tables
- Fixing `summarizeBy` or `formatString` values
- Understanding TMDL syntax rules (indentation, quoting, property ordering)
- Writing multi-line DAX in TMDL format
- Understanding the difference between `///` descriptions and `//` comments

## Critical

- **`///` (triple-slash) sets the `Description` property** on the object that immediately follows it. A `///` line must be immediately followed by a declaration (`measure`, `column`, `table`, etc.); never by a blank line or another `///`. Use `//` for regular comments.
- **Indentation is semantic.** TMDL uses whitespace indentation where depth equals nesting level ([TMDL spec — Indentation](https://learn.microsoft.com/en-us/analysis-services/tmdl/tmdl-overview#indentation)). PBIP files use a single tab per level because Power BI Desktop and the TOM `TmdlSerializer` default to `IndentationMode.Tabs`. Spaces are also valid (`IndentationMode.Spaces`, default 4 per level), but be consistent within a file; mixed or incorrect indentation will break the model. Properties of a table are indented one level; properties of a column (which belongs to a table) are indented two levels.
- **Name quoting rules:** Only quote names that contain spaces, special characters, or start with a digit. Simple names and underscore-prefixed names are unquoted. See the Name Quoting section for details.
- **M expressions and tables share a namespace.** A name declared by `expression <name>` in `expressions.tmdl` and a name declared by `table <name>` in `tables/*.tmdl` collide; Power BI Desktop fails the load with `'duplicate member <name>'`. Pick distinct names; the conventional fix is to suffix the M expression with ` Query` or ` Source` and have partitions reference it via `source = #"<Name> Query"`. `validate_pbip.py` enforces this as an ERROR.

## TMDL File Types

| File | Contents | Location |
|------|----------|----------|
| `model.tmdl` | Model configuration, `ref table` entries, query groups, annotations | `definition/` |
| `database.tmdl` | Compatibility level, model ID | `definition/` |
| `relationships.tmdl` | All relationships between tables | `definition/` |
| `expressions.tmdl` | Shared M expressions and parameters | `definition/` |
| `functions.tmdl` | DAX user-defined functions (reusable parameterized DAX) | `definition/` |
| `roles/<RoleName>.tmdl` | One file per security role (RLS filters, role members, OLS) | `definition/roles/` |
| `perspectives/<Name>.tmdl` | One file per perspective (object membership) | `definition/perspectives/` |
| `dataSources.tmdl` | Legacy data source definitions (if present) | `definition/` |
| `tables/<Name>.tmdl` | Table definition with columns, measures, hierarchies, partitions | `definition/tables/` |
| `cultures/<locale>.tmdl` | Linguistic metadata and translations | `definition/cultures/` |

## Object Nesting Rules

Objects must be nested inside their correct parent. The validator enforces these rules:

| Object | Allowed Parent(s) |
|--------|-------------------|
| `column`, `measure`, `hierarchy`, `partition`, `calculationGroup` | `table` |
| `level` | `hierarchy` |
| `calculationItem` | `calculationGroup` |
| `tablePermission` | `role` |
| `columnPermission` | `tablePermission` |
| `perspectiveTable` | `perspective` |
| `perspectiveColumn`, `perspectiveMeasure`, `perspectiveHierarchy` | `perspectiveTable` |
| `linguisticMetadata`, `translation` | `cultureInfo` |
| `dataAccessOptions` | `model` |
| `formatStringDefinition` | `measure`, `calculationItem` |
| `detailRowsDefinition` | `measure`, `table` |
| `alternateOf` | `column` |
| `member` | `role` |
| `annotation`, `extendedProperty` | any object (including `queryGroup`, `function`, `member`) |
| `ref` | `model`, `table` |

Root-level objects (indent 0 only): `model`, `database`, `table`, `relationship`, `role`, `cultureInfo`, `perspective`, `dataSource`, `expression`, `queryGroup`, `function`.

## Syntax Rules

### Indentation

TMDL uses **whitespace indentation** where depth equals nesting level. PBIP files use a single tab per level (the TOM `TmdlSerializer` default), so all examples below use tabs:

```tmdl
table Product                              // depth 0: top-level declaration
	lineageTag: abc-123                    // depth 1: table property

	measure '# Products' =                // depth 1: measure declaration
			COUNTROWS (                    // depth 3: DAX expression body (one deeper than properties)
			    VALUES ( Product[Name] )   // depth 3: continued
			)                              // depth 3: continued
		formatString: #,##0               // depth 2: measure property
		displayFolder: Measures
audit-tenant-settingsSkill

Automatically invoke this skill whenever the user asks about Fabric tenant settings or Power BI tenant settings or auditing tenant settings. You can use this skill if the user mentions "Fabric administration".

fabric-cliSkill

Expert guidance for using the Fabric CLI (`fab`) to fully interact with Fabric workspaces, items, and configuration. Automatically invoke this skill whenever the user mentions "Fabric" or "Power BI Service" or a "Fabric/Power BI workspace".

connect-pbidSkill

TOM and ADOMD.NET guidance via PowerShell for connecting to Power BI Desktop's local Analysis Services instance. Covers model enumeration, DAX queries, metadata modification, annotations, calendar definitions, field parameters, query tracing, DAX library package management (daxlib.org), and the Desktop Bridge for reloading and screenshotting the report canvas. Automatically invoke when the user mentions "Power BI Desktop", "Analysis Services port", "TOM", "ADOMD", "daxlib", "DAX library", "DAX UDF package", or asks to "connect to PBI Desktop", "query PBI Desktop with DAX", "modify PBI Desktop model", "add a measure to PBI", "capture visual queries", "create a field parameter", "validate DAX", "intercept DAX queries", "install daxlib", "add DAX SVG", "add IBCS", "reload the report canvas", "screenshot a report page", "Desktop Bridge", or to work with the model and report in Power BI Desktop together.

pbipSkill

Expert guidance for the Power BI Project (PBIP) file format; project structure, cross-cutting operations (renames, forking), and PBIX extraction/conversion. Automatically invoke when the user mentions PBIP, PBIX, .pbip/.pbism/.platform files, or asks about "PBIP project structure", "PBIP vs PBIX", "thin report vs thick report", "rename a table", "cascade rename", "fork a PBIP project", "convert pbix to pbip", "extract pbix", "what files are in a PBIP", "PBIP encoding", "definition.pbir", or discusses project-level file structure and post-rename verification.

pbir-formatSkill

Format reference for Power BI Enhanced Report (PBIR) JSON schemas and patterns. Automatically invoke when the user asks about PBIR JSON structure, visual.json properties, PBIR expressions, objects vs visualContainerObjects, theme inheritance, conditional formatting patterns, extension measures, bookmarks, field references, filter formatting, query roles, PBIR page structure, report wallpaper, or any PBIR metadata format question.

create-pbi-reportSkill

Step-by-step workflow for creating complete Power BI reports from scratch using pbir CLI. Covers model discovery, report creation, page layout, theme setup, visual placement, field binding, filtering, formatting, validation, and publishing. Automatically invoke when the user asks to "create a new report", "build a report from scratch", "make a dashboard", "set up a report with KPIs", "create an executive dashboard", "add pages and visuals to a new report".

deneb-visualsSkill

Deneb visual creation, Vega/Vega-Lite spec authoring, and Deneb best practices for PBIR reports. Automatically invoke whenever the user mentions "Deneb" in any context, or asks about Vega/Vega-Lite specs in Power BI, Deneb cross-filtering, Deneb interactivity, pbiColor theme integration, Deneb field name escaping, or Deneb rendering issues.

modifying-theme-jsonSkill

Design, enforce, audit, and validate Power BI report themes. This skill MUST be invoked when a report uses the default or built-in theme, has a minimal custom theme (few or no visualStyles), or has accumulated many visual-level formatting overrides (objects/visualContainerObjects in visual.json); these are signs the theme needs attention. Also automatically invoke when the user asks to "create a theme", "design a theme", "enforce theme compliance", "audit theme adherence", "push formatting to theme", "clear visual overrides", "standardize report formatting", "update theme colors", "change theme typography", "set theme text classes", "validate a theme", "add visual-type overrides to the theme", "copy a theme", "download a theme", "apply a template", or mentions theme design, enforcement, compliance, or visual formatting inconsistency.