Tabular Editor CLI 0.7.0 release

Key Takeaways

  • The Tabular Editor CLI 0.7.0 is now available Limited Public Preview: This release focuses on safer defaults, a more consistent command syntax, and more consistency in showing model changes and reporting problems. The preview period has been extended from September 30 to October 31, 2026, giving you more time to evaluate the CLI while we prepare for general availability.
  • Update existing scripts: Property assignments use -p <Property>=<Value>, several commands move under get or util, and others are removed. The update checklist below maps the old commands to their replacements.
  • Review changes and read results consistently: Model edits show before/after values, and validation, BPA, tests, and queries share a JSON findings structure. Update scripts that read the CLI's JSON output.
  • Run the same built-in BPA checks as in Desktop: The CLI now uses the same built-in rules, IDs, and severities as TE3 Desktop, so switching tools no longer changes which built-in checks run.

This summary is produced by the author, and not by AI.


Release overview

We're excited to share another release of the Tabular Editor CLI: 0.7.0. The Tabular Editor CLI lets you inspect, edit, validate, deploy, and refresh semantic models from your terminal, in CI/CD pipelines, and by agents. This release is about safer defaults for deployment and refresh, a more consistent command syntax, and consistent ways to show model changes and report problems.

NOTE

The TE CLI is in limited public preview and offered for evaluation with a Tabular Editor account. We recommend against using the CLI in production CI/CD pipelines during preview, as commands, flags, and outputs may change before general availability. The preview period has been extended from September 30 to October 31, 2026. This release will stop functioning after that date. After the preview period, a license will be required.

Safer by default

Defaults are the safety net you don't plan for; they help prevent small mistakes from having big consequences. That's why deploy and refresh now default to dry-run; you must pass --execute to actually make changes. These commands print the TMSL script that would run, so you can check what exactly will happen before changing a deployed model or starting a refresh. Add --execute to existing automation that should still deploy or refresh; otherwise, your pipeline will only preview the operation and leave the model unchanged.

You can now also deploy models published to the Power BI Service, and models running in Power BI Desktop, without first exporting them to disk.

  • Use --model for a local file or folder, or -s/-d for a remote source.
  • Use --target-server and --target-database for the deployment target.

Screenshot of a Windows 11 PowerShell terminal showing the Invoiced Sales deployment preview command for Order to Cash - Dev and the corresponding command with --execute

TIP

When updating a deployment or refresh pipeline, add --execute to the steps that should run. Without --execute, those steps only print a preview.

Simplified, consistent commands

There's now one syntax to assign properties: -p <Property>=<Value>, for example te set 'Invoiced Sales/Revenue' -p IsHidden=False --model '<model path>' --save to unhide the Revenue measure. This syntax replaces the paired -q/-i property flags. To read a property, use te get 'Invoiced Sales/Revenue' -p Description --model '<model path>' to return the description of the Revenue object.

We consolidated several commands:

  • save is being renamed to save-as (save is kept as an alias). In interactive mode, save commits staged edits, while save-as writes a model to another location or a different format.
  • get becomes the core command for listing and dependency inspection. ls/ list still work and become aliases of get, as does deps. You can inspect properties, for example, te get 'Invoiced Sales/Revenue' -p Description --model '<model path>' to read the description of the Revenue object in the Invoiced Sales table. Filter objects, with te get Measures --where 'Name=*Revenue*' --model '<model path>' to return only the measures with Revenue in their name; list objects, for example te get Hierarchies --model '<model path>' to list the all hierarchies in the model; and check dependencies, for example te get 'Invoiced Sales/Revenue' --deps --model '<model path>' to see what Revenue depends on and what depends on Revenue. The original commands still work as shortcuts. We recommend updating scripts to use get so listing and dependency checks follow the same command structure.
  • format has been removed. Formatting a model expression now happens with te set '<table>/<object>' --format Expression --model '<model path>' --save. DAX expressions and M scripts can be passed into te util format-dax '<DAX expression>' and te util format-m '<M expression>' for formatting.
  • migrate also moves under the util command group: te util migrate.
  • incremental-refresh has been removed. You can inspect a table's policy with te get '<table>/RefreshPolicy' --model '<model path>', and configure it with te set '<table>/RefreshPolicy' -p '<Property>=<Value>' --model '<model path>' --save. Then apply a policy already saved on a deployed model with te refresh --apply-refresh-policy '<table>' -s '<workspace>' -d '<model>' --execute, which also loads data, whereas the old apply only created partitions. To bootstrap empty partitions without loading data, run te script --inline 'Model.Tables["<table>"].ApplyRefreshPolicy();' -s '<workspace>' -d '<model>'.

Screenshot of a Windows 11 PowerShell terminal showing te get reading the Revenue description and te set assigning a new description with -p Description=Value

TIP

When updating scripts, use the update checklist to find replacements for removed commands and flags. Existing ls and deps commands still work.

More predictable output

Commands that change a model, such as set, add, and remove, will now show the values before and after the change. Changing the Revenue description prints both the old description and the replacement, so you can review the actual edit. The same diff is shown whether you save the change or preview it, and the final status line tells you whether the change was saved, staged, or left unsaved.

diff now uses the same output format as these set, add, and remove editing commands. For structured output with --output-format json, the changes array contains one entry per changed object, with the changed properties and their before/after values grouped together. Previously, diff reported a separate entry for each property. Existigin scripts that read this output will need to account for the new structure and field names, including objectPath and changeKind.

Informational notices like which connection or model you're using now go to the stderr stream, keeping stdout for command results. When you pipe output into another command or save it to a file, meta information like connection notices and progress messages no longer get mixed in with the data. This also applies to text and CSV output.

Screenshot of a Windows 11 PowerShell terminal showing the Revenue description diff, readback before and after --save, and the same change in JSON output

validate, bpa run, test run, and query now all report problems using the same JSON structure. Each output has a summary with error, warning, and information counts, and a findings array with the individual messages, codes, and severities. If the affected ojbect is known, findings also include an objectPath so you can pass it path to get to inspect it. You'll need to update scripts that read this JSON output, but a pipeline can then read findings from all four commands in the same way.

Screenshot of a Windows 11 PowerShell terminal showing the summary and findings fields from validation and BPA JSON for Invoiced Sales

TIP

If your pipeline reads JSON results, update the code that reads those results for the new findings and changes structures. Validation, BPA, tests, and queries can then share the code that reads findings.

Checks and BPA

The CLI's BPA now uses the same built-in rules as TE3 Desktop, including the same IDs and severities. Switching between the two no longer changes which built-in checks run.

To align with TE3, the six VertiPaq rules (those with IDs starting with VPA_) are no longer included, and --vpa-rules has been removed. You can still run these checks if you supply the rules yourself:

  • With bpa run, point the CLI to the rules file with --rules, e.g. te bpa run --rules BPARules.json --model '<model path>'.
  • With Bpa.Analyze() in a C# script, save the rules inside the semantic model. That scripting method doesn't read external rules files.

BPA now also returns a non-zero exit code when a rule cannot be evaluated. Previously, BPA could report success (a zero exit code) even though a rule had failed to run. Pipelines that check the exit code can now detect that rules couldn't be evaluated.

Screenshot of a Windows 11 PowerShell terminal showing built-in BPA rules listed by te bpa rules list

TIP

If you use BPA in a pipeline, check the exit code before allowing the next step. A rule that cannot be evaluated now returns a non-zero exit code.

Source schema

You can now add a table from a data source already defined in the model, with te add '<table>' -t Table --source-table '<schema.table>' --model '<model path>' --save. The CLI will read the source table schema, and creates the table with a partition bound to the source (refresh is still a separate action). You don't need to specify connection details when the model uses one data source; if there are several, use te add '<table>' -t Table --source-table '<schema.table>' --data-source '<data source name>' --model '<model path>' --save to specify which source. This works for SQL Server, Azure SQL, and Fabric SQL sources.

For existing tables, you can now:

  • Add a single data column without recreating the table, with te add '<table>/<column>' -t DataColumn -p 'SourceColumn=<source column>' -p 'DataType=<type>' --model '<model path>' --save.
  • Add new source columns and update changed data types without losing existing column metadata, with te set '<table>' --update-schema --source sql --endpoint '<source server>' --source-database '<source database>' --source-table '<schema.table>' --model '<model path>' --save for a SQL source.

Columns that are in the semantic model but missing from the source flash a warning and are kept unless you pass --drop-removed-columns. A source-column rename is treated as a removal and an addition. To preserve the existing model column and DAX expressions that refer to it, update its binding with te set '<table>/<column>' -p 'SourceColumn=<new name>' --model '<model path>' --save.

Screenshot of a Windows 11 PowerShell terminal showing the Product Key display folder and a schema-update preview for Invoiced Sales from Factview.Invoices

TIP

If a column is renamed in your database, set SourceColumn=<new column name> to update the model column. Keep the column's name in the semantic model unchanged so DAX expressions can still refer to the same model column.

Refresh and tracing

refresh --trace previously stopped collecting events as soon as the refresh command returned, even when the server still had events waiting to be delivered. Logs could therefore end mid-processing, without the events confirming that processing and the commit had finished. The CLI now waits briefly for those final events. Selecting a model with -d '<model ID>' also used to produce an empty log because the CLI did not recognise the model name in the incoming events. The CLI now matches both the model's name and its ID, so --trace can match either.

Refresh durations and throughput are now reported using the server's event timestamps when available. Previously, the CLI used the time each event arrived. Events delivered together could make a long operation appear to finish almost instantly, inflating the rows/second metric. Refresh output also reports measurements such as duration, throughput, CPU time, and memory use instead of subjective verdicts like "excellent" or "below typical".

Post-refresh VertiPaq statistics, such as each table's row count and size in bytes, are now included in JSON output when enabled by vertipaqOnRefresh. Previously, these statistics were only shown in text output. Automation can now read these values from the vertipaq array, so you can track model growth after a refresh.

Screenshot of a Windows 11 PowerShell terminal showing the Invoiced Sales refresh summary for Order to Cash - Dev and the final captured trace events ending at End Rebuild

TIP

When investigating a refresh, use --trace to capture processing events through completion. Duration and throughput use server timestamps when available, so delayed event delivery no longer distorts those measurements.

Other fixes

The release also includes these fixes:

  • PBIP semantic model exports now open correctly in Power BI Desktop.
  • Model exports produce consistent files across Windows, macOS, and Linux.
  • diff detects more collection changes and reports correct object paths.
  • Ctrl-D exits empty prompts; non-interactive commands fail when input is required.
  • Names containing square brackets no longer crash progress spinners.
  • Errors retain terminal coloring when command results are redirected.

Screenshot of a Windows 11 PowerShell terminal showing Invoiced Sales exported with te save-as --serialization pbip and the generated PBIP file

TIP

If your team uses Windows, macOS, and Linux, saving the same model now produces the same line endings and table order. Git reviews show fewer file differences caused only by the operating system.

Update checklist

If you are upgrading from an earlier preview, this checklist will help you update your scripts for 0.7.0. Expand it to see the full list of changes.

Update checklist
UsageBeforeIn 0.7.0
Read a propertyte get '<table>/<object>' -q Description --model '<model path>'te get '<table>/<object>' -p Description --model '<model path>'
Set a propertyte set '<table>/<object>' -q Description -i '<description>' --model '<model path>' --savete set '<table>/<object>' -p 'Description=<description>' --model '<model path>' --save
Select a local modelte get '<table>/<object>' '<model path>'te get '<table>/<object>' --model '<model path>'
Deploy to a targetDeployment used -s / -d for the target and executed by defaultte deploy --model '<model path>' --target-server '<workspace>' --target-database '<model>' --execute
Refresh a deployed modelRefresh executed by defaultte refresh -s '<workspace>' -d '<model>' --execute
Save a deployment previewDeployment script output used --xmlate deploy --model '<model path>' --target-server '<workspace>' --target-database '<model>' > deploy.tmsl
Preview a refreshPreview required --dry-runte refresh -s '<workspace>' -d '<model>'
Save to a format or locationte save --model '<model path>' -o '<output folder>' --serialization tmdlte save-as --model '<model path>' -o '<output folder>' --serialization tmdl; save remains an alias outside interactive mode
List objectste ls --model '<model path>'te get --model '<model path>'; ls and list remain shortcuts
Inspect dependencieste deps '<table>/<object>' --model '<model path>'te get '<table>/<object>' --deps --model '<model path>'; deps remains a shortcut
Format a model expressionte format --path '<table>/<object>' --model '<model path>' --savete set '<table>/<object>' --format Expression --model '<model path>' --save
Format standalone DAXte format -e '<DAX expression>'te util format-dax '<DAX expression>'
Format standalone Mte format -e '<M expression>' --lang mte util format-m '<M expression>'
Look up TE2 command equivalentste migratete util migrate
Read a refresh policyte incremental-refresh show '<table>' --model '<model path>'te get '<table>/RefreshPolicy' --model '<model path>'
Change a refresh policy's rolling windowte incremental-refresh set '<table>' --rolling-window-periods 5 --model '<model path>' --savete set '<table>/RefreshPolicy' -p RollingWindowPeriods=5 --model '<model path>' --save
Apply a saved policy and refreshThe old policy-application command created partitions onlyte refresh --apply-refresh-policy '<table>' -s '<workspace>' -d '<model>' --execute
Create policy partitions without loading datate incremental-refresh apply '<table>' -s '<workspace>' -d '<model>'te script --inline 'Model.Tables["<table>"].ApplyRefreshPolicy();' -s '<workspace>' -d '<model>'
Run a script file and save editste script --script '<script.cs>' --model '<model path>' --savete script --file '<script.cs>' --model '<model path>' --save
Run inline C# and save editste script -e '<C# code>' --model '<model path>' --savete script --inline '<C# code>' --model '<model path>' --save
Compile a script without running itte script --script '<script.cs>' --dry-run --model '<model path>'te script --file '<script.cs>' --validate
Inspect a local modelte load --model '<model path>'te get . --model '<model path>'
Inspect a deployed modelte load -s '<workspace>' -d '<model>'te get . -s '<workspace>' -d '<model>'
Open the desktop applicationThe open command launched TE3 DesktopTabularEditor3.exe
Replace text in model propertiesThe replace command performed bulk replacementste script --file replace-descriptions.cs --model '<model path>' --save; the script is below
Read findings from JSONDifferent structures across commandste validate --model '<model path>' --output-format json returns summary and findings; BPA, tests, and queries use the same findings structure
Read changes from JSONCommand-specific output; diff had an entry per propertyte diff '<before model path>' '<after model path>' --output-format json returns one entry per object in changes, with objectPath, changeKind, and a properties array
Run the six VertiPaq BPA rulesBundled VPA_ rules and --vpa-ruleste bpa run --rules BPARules.json --model '<model path>'; for Bpa.Analyze(), store the rules in the model
Address names containing reserved charactersUnquoted names could be acceptedte get "Invoiced Sales/'Revenue?'" --model '<model path>' in PowerShell

The examples below expand on the checklist entries for deployment, bulk replacements, JSON output, and object names.

The deploy command now uses -s and -d to select the source model. To copy between workspaces, use te deploy -s '<source workspace>' -d '<source model>' --target-server '<target workspace>' --target-database '<target model>' --execute.

For bulk replacements previously done with replace, use a C# script that selects the objects and properties to change. For example, save this as replace-descriptions.cs to replace "euros" with "EUR" in the descriptions of measures in the Invoiced Sales table:

foreach (var measure in Model.Tables["Invoiced Sales"].Measures)
{
    measure.Description = measure.Description?.Replace("euros", "EUR");
}

Preview the description changes with te script --file replace-descriptions.cs --model '<model path>'. To save them, run te script --file replace-descriptions.cs --model '<model path>' --save. Both commands print a before/after diff of the changed descriptions.

Screenshot of a Windows 11 PowerShell terminal showing te script running replace-descriptions.cs against Invoiced Sales without --save, the description changes from euros to EUR, and the final Dry run - nothing saved status

The shared change format applies to diff, set, add, remove, move, script, and bpa run --fix. Update any scripts that read JSON output from these commands.

Object names containing {, }, *, or ? now need quotes around them when used as input. For a measure named Revenue? in the Invoiced Sales table, the PowerShell example is te get "Invoiced Sales/'Revenue?'" --model '<model path>'. The inner single quotes (') tell the CLI that ? is part of the measure's name. The outer double quotes (") keep the full path together when PowerShell passes it to the CLI. Update paths in scripts that address objects with these characters in their names.

Further Reading

In conclusion

The main changes in 0.7.0 give you more visibility into what a command will change and make its results easier to read in automation. Before upgrading an existing pipeline, check which commands need replacing, add --execute where deployment or refresh should run, and update scripts for the new JSON formats.

Download the preview from the Tabular Editor CLI download page. The CLI documentation covers installation, authentication, and command usage.

Screenshot of a Windows 11 PowerShell terminal in the Invoiced Sales.SemanticModel folder showing te --version reporting the installed 0.7.0 release build

Report bugs through GitHub issues, or share questions and feedback in GitHub discussions.

Take your semantic models further with Tabular Editor.

Give Tabular Editor a spin
Plagiarism-freeScanned on September 9, 2026 Human-writtenScanned on September 9, 2026

Related articles

Tabular Editor CLI 0.6.0 release

Tabular Editor CLI 0.6.0 release