From a7459230aac240f10087852d73bcd5b3d6b2eb1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Gr=C3=B8nnerup?= Date: Mon, 20 Apr 2026 11:47:32 +0200 Subject: [PATCH 1/9] Added documentation for new Tabular Editor CLI in Limited Public Preview. This includes new Tabular Editor CLI item and 8 new doc pages covering installation, commands, ci/cd etc. --- .claude/settings.local.json | 7 + content/features/Command-line-Options.md | 9 +- content/features/te-cli/te-cli-auth.md | 199 ++++ content/features/te-cli/te-cli-automation.md | 187 ++++ content/features/te-cli/te-cli-cicd.md | 221 ++++ content/features/te-cli/te-cli-commands.md | 510 ++++++++++ content/features/te-cli/te-cli-config.md | 198 ++++ content/features/te-cli/te-cli-install.md | 150 +++ content/features/te-cli/te-cli-interactive.md | 83 ++ content/features/te-cli/te-cli-migrate.md | 111 +++ content/features/te-cli/te-cli.md | 95 ++ content/features/toc.md | 9 + docfx.json | 940 ++++++++++++++++++ 13 files changed, 2716 insertions(+), 3 deletions(-) create mode 100644 .claude/settings.local.json create mode 100644 content/features/te-cli/te-cli-auth.md create mode 100644 content/features/te-cli/te-cli-automation.md create mode 100644 content/features/te-cli/te-cli-cicd.md create mode 100644 content/features/te-cli/te-cli-commands.md create mode 100644 content/features/te-cli/te-cli-config.md create mode 100644 content/features/te-cli/te-cli-install.md create mode 100644 content/features/te-cli/te-cli-interactive.md create mode 100644 content/features/te-cli/te-cli-migrate.md create mode 100644 content/features/te-cli/te-cli.md create mode 100644 docfx.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 000000000..bee240cf6 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "WebFetch(domain:tabulareditor.com)" + ] + } +} diff --git a/content/features/Command-line-Options.md b/content/features/Command-line-Options.md index be87a94bc..d46cb9677 100644 --- a/content/features/Command-line-Options.md +++ b/content/features/Command-line-Options.md @@ -1,6 +1,6 @@ ---- +--- uid: command-line-options -title: Command Line +title: Command Line (Tabular Editor 2) author: Daniel Otykier updated: 2021-08-26 applies_to: @@ -10,7 +10,10 @@ applies_to: - product: Tabular Editor 3 none: true --- -# Command Line +# Command Line (Tabular Editor 2) + +> [!TIP] +> Looking for the new cross-platform CLI? See @te-cli for the Tabular Editor CLI (Limited Public Preview), a successor that runs on Windows, macOS, and Linux. Tabular Editor can be executed from the command-line to perform various tasks, which may be useful in Automated Build and Deployment scenarios, etc. diff --git a/content/features/te-cli/te-cli-auth.md b/content/features/te-cli/te-cli-auth.md new file mode 100644 index 000000000..c8b0280ad --- /dev/null +++ b/content/features/te-cli/te-cli-auth.md @@ -0,0 +1,199 @@ +--- +uid: te-cli-auth +title: Authentication and Connections +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Authentication and Connections + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +The Tabular Editor CLI authenticates to Power BI Service, Microsoft Fabric, and Azure Analysis Services using the same Power BI Desktop client ID that Tabular Editor 3 uses. Tokens are cached locally so you authenticate once and re-run commands silently until the refresh token expires (typically 90 days). + +## Authentication methods + +The CLI supports the full Azure Identity credential chain: + +| Method | When to use | `--auth` value | +| -- | -- | -- | +| Interactive browser | Local development — opens the system browser | `interactive` (default) | +| Device code | SSH sessions, headless VMs, devcontainers | `device-code` | +| Service principal (client secret) | Automation, CI/CD | `env` or pass `-u / -p / -t` | +| Service principal (certificate) | Automation with certificate-based auth | Pass `--certificate` | +| Environment variables | `AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID` | `env` | +| Managed identity | Azure VMs, Azure Container Apps, Azure Functions | `managed-identity` | + +The default (`auto`) tries environment credentials first, then falls back to interactive browser. + +## `te auth login` + +Authenticate and cache the result for subsequent commands: + +```bash +# Browser-based interactive login (default) +te auth login + +# Device code flow (headless / SSH / CI) +te auth login --device-code + +# Service principal with client secret +te auth login -u -p -t + +# Service principal — read secret from stdin +echo $AZURE_CLIENT_SECRET | te auth login -u -p - -t + +# Service principal with certificate +te auth login -u -t --certificate ./sp.pfx --certificate-password ... + +# Managed identity (Azure-hosted) +te auth login --identity +``` + +> [!WARNING] +> Passing secrets directly on the command line is visible in `ps` output and shell history. Prefer the `AZURE_CLIENT_SECRET` environment variable, or pipe the secret via stdin with `-p -`. + +## `te auth status` + +Display the current authentication state without opening a browser: + +```bash +te auth status +te auth status --output json +``` + +Exit code is `0` when a valid session exists, `1` when not logged in or expired. + +## `te auth logout` + +Clear all cached credentials: + +```bash +te auth logout +``` + +## Credential storage + +Tokens are cached under your home directory. File permissions are restricted to the current user (`0600` on POSIX): + +| Platform | Location | Notes | +| -- | -- | -- | +| Windows | `%USERPROFILE%\.te-cli\auth-record.json` | Token cache encrypted via DPAPI through Azure.Identity | +| Linux | `~/.te-cli/auth-record.json` | Token cache via libsecret through Azure.Identity | +| macOS | `~/.te-cli/token-cache.bin` | File-based cache (bypasses Keychain to avoid repeated prompts) | + +Device-code and interactive browser flows use separate record files so they can coexist. + +## `te connect` — set the active connection + +`te connect` persists an active connection for the current terminal session. Subsequent commands that take `-s` / `-d` can omit them: + +```bash +# Remote workspace +te connect my-workspace my-model + +# Local TMDL folder or .bim file +te connect ./my-model + +# Connect to a running Power BI Desktop instance (Windows only) +te connect --local + +# Show the active connection +te connect +``` + +Active-connection state is per-terminal-session: opening a new terminal starts fresh. + +## Connecting to different clouds + +The CLI detects the correct scope from the server URL for: + +- Power BI Service and Fabric (commercial, US Gov, China, Germany clouds) +- Azure Analysis Services (`asazure://...`) +- Local SSAS (`localhost`, named instances — Windows only) + +Pass an XMLA endpoint, workspace name, or `powerbi://` URL as `--server`: + +```bash +te connect "powerbi://api.powerbi.com/v1.0/myorg/Finance" "Revenue Model" +te connect "asazure://westeurope.asazure.windows.net/myaas" "MyModel" +te connect localhost "AdventureWorks" +``` + +## Connection profiles + +For repeated use of the same connection — especially when you deploy to multiple environments — save named profiles: + +```bash +# Save remote and local profiles +te profile set prod -s my-workspace -d my-model --description "Production" +te profile set dev --model ./model --description "Local dev TMDL" + +# List and inspect +te profile list +te profile show prod + +# Use a profile as the active connection +te connect --profile prod + +# One-shot use without changing the active connection +te deploy ./model --profile staging --force +``` + +Profiles can also carry behavioral overrides that take effect whenever the profile is active: + +```bash +# In dev, disable the BPA gate on deploy and loosen validation +te profile set dev --bpa-on-deploy false --validate-on-mutation false + +# In prod, force auto-format before any mutation +te profile set prod --auto-format true +``` + +See @te-cli-config for the full list of overridable behaviors. + +## Non-interactive authentication + +For CI/CD pipelines, agents, or any unattended context, avoid interactive flows by combining: + +- The `--non-interactive` global flag (fails fast instead of prompting). +- One of the non-interactive auth methods: `env`, `managed-identity`, or explicit service principal credentials. + +Environment-based example for a pipeline: + +```bash +export AZURE_CLIENT_ID= +export AZURE_CLIENT_SECRET= +export AZURE_TENANT_ID= + +te deploy ./model -s my-workspace -d my-model \ + --auth env \ + --non-interactive \ + --force \ + --ci github +``` + +See @te-cli-cicd for complete GitHub Actions and Azure DevOps Pipelines examples. + +## Environment variable overrides + +| Variable | Purpose | +| -- | -- | +| `AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID` | Service principal credentials (used by `--auth env`). | +| `TE_CONFIG` | Override the config file path — see @te-cli-config. | +| `TE_COMPAT=te2` | Force TE2-compatibility mode — see @te-cli-migrate. | +| `TE_DEBUG=1` | Enable debug logging to stderr (connection strings, auth flow, timing). | + +## Next steps + +- @te-cli-commands — what you can do once connected. +- @te-cli-config — configuration and profile behavior. +- @te-cli-cicd — pipeline examples using service principals and managed identity. diff --git a/content/features/te-cli/te-cli-automation.md b/content/features/te-cli/te-cli-automation.md new file mode 100644 index 000000000..0ec3d70df --- /dev/null +++ b/content/features/te-cli/te-cli-automation.md @@ -0,0 +1,187 @@ +--- +uid: te-cli-automation +title: Automation and Scripting +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Automation and Scripting + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +The Tabular Editor CLI is designed as a composable building block. Every command supports structured output, disables interactive prompts on demand, and returns predictable exit codes. The same primitives work equally well for shell pipelines, Python scripts, PowerShell automation, and agent-driven workflows. + +## Structured output + +Use `--output` to switch any command between text (human-readable) and machine-readable formats: + +| Format | Use for | Notes | +| -- | -- | -- | +| `auto` (default) | General use | Text for TTY, JSON when stdout is piped or redirected. | +| `text` | Force text output | Useful when you want text in a CI log. | +| `json` | Programmatic consumers | Always valid JSON to stdout; errors and warnings go to stderr as separate JSON objects. | +| `csv` | Tabular results (`query`, `bpa`, `vertipaq`) | RFC 4180 escaping. | + +```bash +te ls --output json +te query -q "EVALUATE VALUES('Date'[Year])" --output csv +te bpa run --output json +``` + +> [!TIP] +> When stdout is piped, `auto` already emits JSON. Explicit `--output json` is only necessary when you want JSON on a TTY, or when a consumer expects it regardless of how the command is invoked. + +## Non-interactive mode + +Add `--non-interactive` to any command to disable confirmation prompts, credential picklists, and guided wizards. If the command needs input it cannot resolve from flags, environment, or config, it exits non-zero with an actionable error instead of hanging. + +```bash +te deploy ./model --non-interactive --force --ci github +``` + +## Exit codes + +| Exit | Meaning | +| -- | -- | +| `0` | Success. | +| `1` | Generic failure — invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity ≥ error. | +| `2` | Used by `te diff` to indicate models differ (distinct from `0` identical and non-zero errors). | + +Combine exit codes with `--ci ` annotations and `--trx ` to surface rich failure information in CI — see @te-cli-cicd. + +## Errors on stderr + +Errors, warnings, and the preview banner are written to **stderr**; structured data is written to **stdout**. This means you can pipe JSON safely without it being contaminated by progress indicators or diagnostic messages: + +```bash +te ls --output json | jq '.[] | .name' +te vertipaq --output json > stats.json +``` + +## Python + +Invoke the CLI from Python with `subprocess.run`, request JSON, and parse stdout: + +```python +import json +import subprocess + +def query(server: str, database: str, dax: str) -> list[dict]: + result = subprocess.run( + ["te", "query", + "-s", server, + "-d", database, + "-q", dax, + "--output", "json", + "--non-interactive"], + check=True, + capture_output=True, + text=True, + ) + return json.loads(result.stdout) + +rows = query("Finance", "Revenue Model", "EVALUATE TOPN(10, 'Sales')") +for row in rows: + print(row) +``` + +Capture structured errors from stderr: + +```python +import json +import subprocess + +result = subprocess.run( + ["te", "deploy", "./model", + "-s", "Finance", "-d", "Revenue", + "--output", "json", "--non-interactive", "--force"], + capture_output=True, text=True, +) + +if result.returncode != 0: + try: + err = json.loads(result.stderr.strip().splitlines()[-1]) + print("Deploy failed:", err.get("error"), "— hint:", err.get("hint")) + except json.JSONDecodeError: + print("Deploy failed:\n", result.stderr) +``` + +## PowerShell + +PowerShell handles JSON natively. Because `te` is a normal console binary, there is no need for the `start /wait` dance required by `TabularEditor.exe`: + +```powershell +$rows = te query -s Finance -d Revenue -q "EVALUATE TOPN(10, 'Sales')" --output json --non-interactive + | ConvertFrom-Json + +$rows | Format-Table + +# Check exit code after the pipeline +if ($LASTEXITCODE -ne 0) { + Write-Error "Query failed with exit $LASTEXITCODE" + exit $LASTEXITCODE +} +``` + +Read secrets from the environment rather than passing them as plaintext: + +```powershell +$env:AZURE_CLIENT_ID = "" +$env:AZURE_CLIENT_SECRET = "" +$env:AZURE_TENANT_ID = "" + +te deploy ./model ` + -s my-workspace -d my-model ` + --auth env --non-interactive --force --ci vsts +``` + +## Bash + +Compose commands with pipes and `jq`. The CLI's text output is colorized for humans, but switching to `--output json` gives you a clean shape to work with: + +```bash +# Count measures per table +te ls --type measure --output json \ + | jq -r '.[] | .table' \ + | sort | uniq -c | sort -rn +``` + +```bash +# Fail the shell script if BPA finds any errors +te bpa run --fail-on error --output json > bpa.json \ + || { echo "BPA gate failed"; jq '.violations' bpa.json; exit 1; } +``` + +## Composability example + +Generating a refresh TMSL script and version-controlling it is three commands: + +```bash +te connect MyWorkspace MyModel +te refresh --type full --dry-run > refresh.tmsl +cat refresh.tmsl +``` + +The resulting TMSL can be reviewed in a pull request, committed, executed by the CLI (`te refresh --type full`), handed to a DBA, or applied by any XMLA-compatible tool. The CLI becomes a building block rather than a black box. + +## Useful patterns + +- **Idempotent removes.** `te rm Sales/OldMeasure --if-exists --save` exits `0` whether or not the object existed — safe to re-run. +- **Dry-run diffs.** `te replace` is dry-run by default; add `--save` only when you're satisfied with the preview. +- **Emit TMSL for review.** `te deploy ./model --xmla deploy.tmsl` produces the deployment script without touching the server — useful for DBA review or manual apply. +- **Path-only output.** `te ls --paths-only` and `te find --paths-only` emit one object path per line, ideal for piping to `xargs`, `te get`, or `te set`. +- **Benchmarking queries.** `te query --trace --cold --runs 5` runs a DAX query with cold cache, five iterations, and captures FE/SE trace events. + +## Related pages + +- @te-cli-cicd — pipeline-specific patterns and YAML examples. +- @te-cli-commands — full command reference. +- @te-cli-interactive — when interactive mode fits better than scripting. diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md new file mode 100644 index 000000000..a193c2d14 --- /dev/null +++ b/content/features/te-cli/te-cli-cicd.md @@ -0,0 +1,221 @@ +--- +uid: te-cli-cicd +title: CI/CD Integration +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# CI/CD Integration + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +The Tabular Editor CLI is designed for unattended execution in continuous integration and delivery pipelines. A single binary, structured output, non-interactive mode, native CI annotations for GitHub Actions and Azure DevOps, and VSTEST-compatible test results make it a natural replacement for ad-hoc TE2 invocations. + +> [!WARNING] +> During preview, we recommend against using the CLI in **production** pipelines. Commands, flags, and outputs may change before GA. Build and evaluate in non-production pipelines first; share feedback so the GA shape matches your needs. + +## What makes the CLI CI-friendly + +- **Single self-contained binary.** No runtime install, no `TabularEditor.exe`, no `start /wait`. +- **`--non-interactive` global flag.** Disables every prompt; fails fast with actionable errors. +- **`--force`** on mutating commands (`te deploy`, `te refresh`) skips confirmation prompts. +- **`--ci vsts` / `--ci github`.** Emit native pipeline annotations to stderr. +- **`--trx `.** Produce VSTEST results consumable by Azure DevOps test publishing. +- **Structured errors.** `--output json` emits `{"error": "...", "hint": "..."}` to stderr so pipeline steps can fail with a useful message. + +## GitHub Actions + +A complete deploy + test workflow. The example assumes a service principal stored in repository secrets (`AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID`). + +```yaml +name: Deploy semantic model + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + env: + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + steps: + - uses: actions/checkout@v4 + + - name: Download Tabular Editor CLI + run: | + # TBD: replace with the official download URL once confirmed. + curl -L -o te.zip "" + unzip te.zip -d $HOME/.local/bin + chmod +x $HOME/.local/bin/te + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Validate + run: te validate ./model --ci github --trx validate.trx + + - name: Best Practice Analyzer (gate) + run: te bpa run ./model --fail-on error --ci github --trx bpa.trx + + - name: Deploy + run: | + te deploy ./model \ + -s "${{ vars.WORKSPACE }}" \ + -d "${{ vars.MODEL }}" \ + --auth env \ + --non-interactive \ + --force \ + --ci github + + - name: Regression tests + run: | + te test run \ + -s "${{ vars.WORKSPACE }}" \ + -d "${{ vars.MODEL }}" \ + --auth env --non-interactive \ + --ci github --trx tests.trx + + - name: Publish test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: trx-results + path: '*.trx' +``` + +## Azure DevOps Pipelines + +Equivalent YAML for Azure DevOps. `--ci vsts` emits `##vso[...]` commands that the pipeline interprets as errors, warnings, and task-status updates. + +```yaml +trigger: + - main + +pool: + vmImage: 'windows-latest' + +variables: + - group: 'te-cli-secrets' # Contains AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID + +steps: + - checkout: self + + - task: PowerShell@2 + displayName: 'Install Tabular Editor CLI' + inputs: + targetType: 'inline' + script: | + # TBD: replace with the official download URL once confirmed. + Invoke-WebRequest -Uri "" -OutFile te.zip + Expand-Archive te.zip -DestinationPath $(Agent.ToolsDirectory)\te + Write-Host "##vso[task.prependpath]$(Agent.ToolsDirectory)\te" + + - script: te validate ./model --ci vsts --trx validate.trx + displayName: 'Validate' + + - script: te bpa run ./model --fail-on error --ci vsts --trx bpa.trx + displayName: 'BPA gate' + + - script: | + te deploy ./model ^ + -s "$(WORKSPACE)" -d "$(MODEL)" ^ + --auth env --non-interactive --force --ci vsts + displayName: 'Deploy' + env: + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + AZURE_TENANT_ID: $(AZURE_TENANT_ID) + + - script: te test run -s "$(WORKSPACE)" -d "$(MODEL)" --auth env --non-interactive --ci vsts --trx tests.trx + displayName: 'Regression tests' + env: + AZURE_CLIENT_ID: $(AZURE_CLIENT_ID) + AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET) + AZURE_TENANT_ID: $(AZURE_TENANT_ID) + + - task: PublishTestResults@2 + condition: always() + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' +``` + +## BPA gate patterns + +`te deploy` and `te save` run the Best Practice Analyzer as a pre-flight gate by default. Three behaviors are worth picking up front: + +- **Enforce** — the default. Pipeline fails if BPA finds violations at severity ≥ error. Pair with `--fail-on warning` on a standalone `te bpa run` step if you want warnings to fail too. +- **Auto-fix** — `--fix-bpa` applies `fixExpression`s in memory for the deployed artifact. Source files are not modified. Useful when the source of truth lives in the model and you want deploys to normalize style without developer intervention. +- **Bypass** — `--skip-bpa` disables the gate for a single command. Useful for emergency hotfixes; not recommended as a default. + +```bash +# Treat warnings as failures in PR validation +te bpa run ./model --fail-on warning --ci github --trx bpa.trx + +# Auto-fix during deploy (source unchanged) +te deploy ./model -s my-ws -d my-model --fix-bpa --force --ci github + +# Emergency bypass +te deploy ./model -s my-ws -d my-model --skip-bpa --force --ci github +``` + +See @te-cli-config for controlling the BPA gate globally via `bpaOnDeploy` / `bpaOnSave` config keys. + +## Refresh patterns + +Refresh in pipelines is typically a follow-up step after deploy. Use `--non-interactive` and pick a deterministic `--type`: + +```bash +# Full refresh of the whole model after deploy +te refresh -s my-ws -d my-model --type full --non-interactive --ci github + +# Refresh a single fact table (e.g., daily incremental pipeline) +te refresh -s my-ws -d my-model --table Sales --type full --non-interactive + +# Recalculate only (useful after calculation-group changes) +te refresh -s my-ws -d my-model --type calculate --non-interactive +``` + +For incremental refresh workflows, combine `--apply-refresh-policy`, `--effective-date `, and `--partition ` flags. See @te-cli-commands for details. + +## Artifact patterns + +Emit TMSL or XMLA as an artifact without deploying, so DBAs or a later job can review or apply it: + +```bash +# Produce the XMLA/TMSL script that would deploy — do not deploy +te deploy ./model -s my-ws -d my-model --xmla deploy.tmsl --force + +# Produce the TMSL refresh command — do not execute +te refresh -s my-ws -d my-model --type full --dry-run > refresh.tmsl +``` + +Commit these artifacts to git, upload them to the pipeline's artifact storage, or pass them between jobs. They're plain text and diff cleanly in pull requests. + +## Secret handling + +| Approach | When to use | Notes | +| -- | -- | -- | +| Service principal via env vars (`AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID`, `--auth env`) | General CI/CD | Map pipeline secrets to environment variables at the step or job level. Never pass secrets in command arguments. | +| Service principal via flags (`te auth login -u ... -p -`, reading secret from stdin) | One-off automation | Pipe the secret rather than interpolating it: `echo $SECRET | te auth login -u $ID -p - -t $TENANT`. | +| Managed identity (`--auth managed-identity`) | Azure VMs, Container Apps, Azure Functions | No secrets to manage. Preferred in Azure-hosted environments. | +| Certificate (`--certificate `) | Enterprise scenarios with cert rotation | Mount the certificate as a secure file step; pass `--certificate-password` via env. | + +> [!WARNING] +> Do not echo secrets or the output of `te auth status` to pipeline logs. The CLI writes warnings to stderr when secrets are passed on the command line — respect those warnings in CI. + +## Related pages + +- @te-cli-auth — authentication methods in detail. +- @te-cli-config — configuration and profile overrides. +- @te-cli-automation — general scripting patterns. +- @te-cli-migrate — migrating an existing TE2-based pipeline. diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md new file mode 100644 index 000000000..edf57322f --- /dev/null +++ b/content/features/te-cli/te-cli-commands.md @@ -0,0 +1,510 @@ +--- +uid: te-cli-commands +title: Command Reference +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Command Reference + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +This page gives a short description and one example per command. Every command accepts `--help` for exhaustive flag documentation: + +```bash +te --help +te --help +``` + +> [!NOTE] +> During preview, the CLI's `--help` output is the authoritative reference for flags and options. The content on this page is hand-curated and will lag `--help` for anything added between preview releases. + +## Object path syntax + +Most commands accept object paths of the form: + +- `Sales` — a table. +- `Sales/Revenue` — a measure or column. +- `Sales/Measures` — a sub-container inside a table (`Measures`, `Columns`, `Partitions`, `Hierarchies`). +- `Relationships`, `Roles`, `Perspectives`, `Cultures` — model-level containers. + +Paths are consistent across `te get`, `te set`, `te add`, `te rm`, `te mv`, `te find`, `te replace`, and `te ls`. + +## Global options + +These flags are available on every command and sit before or after the subcommand name. + +| Option | Description | +| -- | -- | +| `-m, --model ` | Path to semantic model (TMDL folder, `.bim` file, or TE folder). | +| `-s, --server ` | Workspace name or endpoint (e.g., `MyWorkspace`, `powerbi://...`, `asazure://...`, `localhost`). | +| `-d, --database ` | Semantic model name on the workspace. | +| `--local` | Connect to a locally running Power BI Desktop instance (Windows only). | +| `--auth ` | Auth method: `auto`, `interactive`, `device-code`, `env`, `managed-identity` (default: `auto`). | +| `--output ` | Output format: `auto`, `text`, `json`, `csv` (default: `auto` — text for TTY, JSON for pipes). | +| `--recent [N]` | Use a recently used model. No value = interactive picker; `N` = Nth most recent (1 = last used). | +| `--non-interactive` | Disable all interactive prompts. Fail with an actionable error if required input is missing. | +| `--debug` | Enable debug logging to stderr (connection strings, auth flow, timing). | + +For commands that read a model, the resolution order is: positional `` argument → `--model` global flag → `--server`/`--database` (remote) → active connection from `te connect` → `--recent`. + +## Model I/O + +### load + +Load a semantic model and display a summary. + +```bash +te load ./model # TMDL folder +te load model.bim # BIM file +te load -s MyWorkspace -d MyModel # Remote workspace +``` + +### save + +Save a model to disk in a specified format. + +- `-o, --output-path ` — target file or folder (required). +- `--format ` — `tmdl` (default), `bim`, `te-folder`, `pbip`, `database.json`. +- `--force` — skip validation and overwrite existing output. +- `--skip-bpa` / `--fix-bpa` — bypass or auto-fix the BPA gate. +- `--supporting-files` — generate Fabric supporting files (`.platform`, `definition.pbism`). + +```bash +te save ./model.bim -o ./tmdl-out # Convert BIM to TMDL +te save -o ./project --format pbip # Save as a PBIP project +``` + +### export + +Export a model from a workspace to local disk. + +```bash +te export -o ./out -s my-workspace -d my-model +te export -o ./model.bim --format bim +``` + +### open + +Open a model in Tabular Editor 3 Desktop (requires TE3 to be installed). + +```bash +te open ./my-model +``` + +### init + +Create a new empty semantic model at the given path. + +```bash +te init ./new-model +``` + +## Model editing + +### set + +Set a property on a model object. + +- `-q ` — property name (e.g., `expression`, `formatString`, `description`, `isHidden`). +- `-i ` — value (use `-` to read from stdin). +- `--save` / `--save-to ` — persist changes. + +```bash +te set Sales/Amount -q expression -i "SUM(Sales[Amt])" --save +te set Sales -q isHidden -i true --save +``` + +### add + +Add an object to the model. The type is inferred from the `.Type` suffix on the path: +`.Measure`, `.Table`, `.CalculatedColumn`, `.Role`, plus relationship shorthand +`"Sales[Key]->Dim[Key]"`. + +```bash +te add Sales/Revenue.Measure -i "SUM(Sales[Amount])" --save +te add "Sales[ProdKey]->Product[ProdKey]" --save +``` + +For data-bound tables, `te add` also supports schema detection from SQL, Lakehouse, or Warehouse sources. See `te add --help` for `--source`, `--endpoint`, `--source-table`, `--columns`, etc. + +### rm + +Remove an object. Checks dependents by default; use `--force` to bypass, `--if-exists` for idempotent removes. + +```bash +te rm Sales/Revenue --save +te rm Sales/Revenue --dry-run # Preview only +te rm Sales/OldMeasure --if-exists --save # Idempotent +``` + +### mv + +Move or rename a model object. + +```bash +te mv Sales/Revenue Finance/Revenue --save # Move measure to another table +te mv Sales/Revenue Sales/TotalRevenue --save # Rename measure +``` + +### replace + +Find and replace text across model objects. Dry-run by default; add `--save` to apply. + +- `--in ` — `names`, `expressions`, `descriptions`, `displayFolders`, `formatStrings`, `annotations`, `all`. +- `--regex`, `--case-sensitive`. + +```bash +te replace "OldTable" "NewTable" --in expressions --save +te replace "SUM" "SUMX" --regex --in expressions --save +``` + +## Inspection + +### ls + +List objects with filesystem-like navigation. + +```bash +te ls # Tables (active model) +te ls Sales # Columns and measures in Sales +te ls Sales/Measures # Only measures +te ls --type measure # All measures across tables +te ls --paths-only # One path per line, suitable for piping +``` + +### get + +Get properties of a model object. + +- `-q, --query ` — fetch a single property (e.g. `expression`, `formatString`). + +```bash +te get Sales/Amount -q expression # Print DAX +te get Model -q description +``` + +### find + +Search for text across model objects. + +- `--in ` — as per `te replace` (default `all`). +- `--regex`, `--case-sensitive`, `--paths-only`. + +```bash +te find "CALCULATE" --in expressions +te find "Revenue" --in names +``` + +### diff + +Compare two models for structural differences. Exit codes: `0` = identical, `1` = differences found, `2` = error. + +```bash +te diff ./model-v1 ./model-v2 +te diff old.bim new.bim +``` + +### deps + +Analyze an object's upstream and downstream dependencies. + +```bash +te deps "Sales/Revenue" +``` + +## Analysis and quality + +### validate + +Validate model expressions, schema integrity, and TOM errors. + +- `--ci ` — emit CI annotations to stderr: `vsts` or `github`. +- `--trx ` — write results as a VSTEST `.trx` file. + +```bash +te validate ./model +te validate --ci github --trx results.trx +``` + +### bpa run + +Run Best Practice Analyzer rules against a model. + +- `-r, --rules ` — additional BPA rule file(s); repeatable. +- `--fix` — apply auto-fix expressions where rules define them. +- `--fail-on ` — `error` (default) or `warning`. +- `--ci ` / `--trx ` — CI annotations and TRX output. +- `--skip-bpa`, `--no-model-rules`, `--no-defaults`, `--rule `, `--path `, `--vpax `, `--vpa-rules`. + +```bash +te bpa run --fail-on error --ci github +te bpa run --fix --save +te bpa run --rule PERF_UNUSED_HIDDEN_COLUMN +``` + +### bpa rules + +List and inspect BPA rules from all sources (built-in, user, machine, model). + +```bash +te bpa rules list # Active rules +te bpa rules list --all # Include disabled and ignored rules +te bpa rules list --ignored +``` + +### vertipaq + +Analyze VertiPaq storage statistics. + +- `--columns`, `--relationships`, `--partitions`, `--all`. +- `--export ` / `--import ` — round-trip to VPAX. +- `--obfuscate` — obfuscate names and expressions in exported VPAX. +- `--top `, `--stats`, `--annotate`, `--save`. + +```bash +te vertipaq # Columns by size (default) +te vertipaq --all # Tables, columns, relationships, partitions +te vertipaq --export stats.vpax +te vertipaq --import stats.vpax # Analyze offline +``` + +### format + +Format DAX or M/Power Query expressions. + +- `-e, --expression ` — format a single inline expression. +- `-p, --path ` — format a specific measure/column. +- `--lang ` — default `dax`. +- `--save` / `--save-to` — persist formatted expressions. + +```bash +te format --save # Format all DAX +te format -p Sales/Amount --save # Single measure +te format -e "SUM ( Sales[Amount] )" # Inline +te format --lang m --save # Format M +``` + +## Execution + +### query + +Execute a DAX query against a deployed model. + +- `-q, --query ` — inline query. +- `-f, --file ` — query from file. +- `--limit ` — default 100. +- `-o, --output-file ` — write results to file (`.csv`, `.tsv`, `.json`, `.dax`). +- `--trace`, `--cold`, `--plan`, `--runs ` — performance tracing and benchmarking. +- `--no-validate` — skip pre-execution DAX semantic validation. + +```bash +te query -q "EVALUATE TOPN(5, 'Sales')" -s my-ws -d my-model +te query -f query.dax --output json +``` + +### script + +Execute one or more C# scripts against a semantic model. + +- `-S, --script ` — `.cs` / `.csx` file (repeatable). +- `-e, --expression ` — inline C# (use `-` for stdin). +- `--save` / `--save-to` / `--format`. +- `--dry-run`, `--timeout `. + +```bash +te script --script fix.cs --save +te script -e "Info(Model.Tables.Count)" +echo "Info(Model.Name);" | te script -e - +``` + +### macro + +Manage and run Tabular Editor 3 macros from `MacroActions.json`. + +```bash +te macro list # List macros +te macro run # Run a macro +te macro add # Add a macro +te macro set # Update macro properties +te macro rm # Remove a macro +te macro sort # Sort and re-assign IDs +``` + +## Deployment and refresh + +### deploy + +Deploy a semantic model to Power BI, Fabric, or Azure Analysis Services. + +- `-s, --server` / `-d, --database` — target workspace and model. +- `--deploy-full` — overwrite + connections + partitions + shared expressions + roles + role members. +- `--deploy-connections`, `--deploy-partitions`, `--skip-refresh-policy`, `--deploy-roles`, `--deploy-role-members`, `--deploy-shared-expressions`, `--create-only`. +- `--xmla ` — generate XMLA/TMSL script instead of deploying (`-` for stdout). +- `--skip-bpa` / `--fix-bpa` — bypass or auto-fix the BPA gate. +- `--force` — skip interactive confirmation (required for CI). +- `--ci ` — `vsts` or `github`. +- `--profile ` — one-shot use of a saved @te-cli-auth profile. + +```bash +te deploy ./model -s my-workspace -d my-model --force --ci github +te deploy ./model --xmla script.tmsl # Generate TMSL only +te deploy ./model --profile staging --force +``` + +> [!IMPORTANT] +> `te deploy` runs the Best Practice Analyzer as a gate before executing. In interactive mode, a summary + confirmation prompt is shown with **`n` as the safe default**. In CI, pass `--force` to skip the prompt. See @te-cli-config for BPA gate configuration. + +### refresh + +Trigger a data refresh on a deployed model. + +- `--type ` — `full`, `dataonly`, `automatic`, `calculate`, `clearvalues`, `defragment`, `add` (default: `automatic`). +- `--table ` — refresh specific table(s); repeatable. +- `--partition ` — refresh specific partition(s). +- `--apply-refresh-policy`, `--effective-date `, `--max-parallelism `. +- `--dry-run` — output the TMSL script without executing. +- `--no-progress`, `--trace [path]`. + +```bash +te refresh --type full # Full refresh +te refresh --table Sales --type full # Single table +te refresh --type full --dry-run > refresh.tmsl # Emit TMSL only +``` + +### incremental-refresh + +Manage incremental refresh policies on tables. + +```bash +te incremental-refresh show +``` + +Additional subcommands (`set`, `remove`, `apply`) are documented via `te incremental-refresh --help`. + +## Testing + +### test run + +Run a suite of DAX assertion tests against a deployed model. + +- `--suite ` — test-suite directory (default: `.te-tests/`). +- `--tag ` — only tests with this tag. +- `--fail-on ` — `error` (default) or `warning`. +- `--ci `, `--trx ` — CI annotations and TRX output. + +```bash +te test run --ci github --trx results.trx +te test run --tag revenue +``` + +### test init / spec / use / list / snapshot / compare + +Additional subcommands scaffold tests, print the assertion spec format, switch the active suite, list suites, capture snapshots, and compare models. See `te test --help` for details. + +```bash +te test init --example # Scaffold an example suite +te test spec # Print the full assertion format reference +te test init --from-model --model ./my-model # Generate stubs from your measures +``` + +## Connection and auth + +### connect + +Set (or display) the active connection for the current terminal session. See @te-cli-auth. + +```bash +te connect # Show current active connection +te connect my-workspace my-model # Remote +te connect ./model # Local +te connect --local # Power BI Desktop (Windows) +te connect --profile prod # Activate a saved profile +``` + +### auth login / status / logout + +Manage cached authentication. See @te-cli-auth. + +### profile list / show / set / remove + +Manage named connection profiles. See @te-cli-auth. + +## Configuration + +### config show / paths / init / set + +View and manage CLI configuration and TE3 path overrides. See @te-cli-config. + +```bash +te config show # Display all settings +te config paths # Resolved TE3 file paths +te config init # Create default config +te config set autoFormat true +``` + +### license + +Manage CLI license state. + +```bash +te license activate +``` + +### migrate + +Reference guide showing how legacy Tabular Editor 2 CLI flags map to the new CLI. Useful as a live lookup while porting a TE2-based pipeline. See @te-cli-migrate for the full migration guide. + +```bash +te migrate # Full flag mapping table +te migrate -A # Look up a single TE2 flag +te migrate --output json # Machine-readable mapping +``` + +## Shell + +### interactive + +Start a guided REPL session with a model-aware prompt. See @te-cli-interactive. + +```bash +te interactive # Connect later +te interactive ./model # Start with a local model +te interactive -s MyWorkspace -d MyModel # Start with a remote model +``` + +### completion + +Generate a shell completion script. See @te-cli-install. + +```bash +te completion bash +te completion zsh +te completion pwsh +``` + +## Exit codes + +| Exit | Meaning | +| -- | -- | +| `0` | Success. | +| `1` | Generic failure (invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity ≥ error). | +| `2` | Non-zero diff (`te diff`) — models differ. | + +For fine-grained control in CI pipelines, combine exit codes with `--ci ` annotations and `--trx` results files — see @te-cli-cicd. + +## Related pages + +- @te-cli — overview and framing. +- @te-cli-install — install and set up the CLI. +- @te-cli-auth — authenticate and manage connections. +- @te-cli-config — configuration file, BPA gate, post-mutation behavior. +- @te-cli-migrate — TE2 → TE3 flag mapping. diff --git a/content/features/te-cli/te-cli-config.md b/content/features/te-cli/te-cli-config.md new file mode 100644 index 000000000..d7468cc7e --- /dev/null +++ b/content/features/te-cli/te-cli-config.md @@ -0,0 +1,198 @@ +--- +uid: te-cli-config +title: Configuration +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Configuration + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +The Tabular Editor CLI reads optional configuration from a JSON file. Configuration controls three things: where the CLI looks for Tabular Editor 3's shared data files (Preferences, macros, BPA rules), behavioral defaults (BPA gates, auto-format, validation), and the list of saved connection profiles. + +Most users don't need to edit the file directly — `te config show`, `te config set `, and `te profile set` cover the common operations. + +## Config file location + +Resolution order: + +1. `$TE_CONFIG` environment variable (if set and the file exists). +2. `~/.config/te/config.json` (on Windows, `%USERPROFILE%\.config\te\config.json`). +3. No config file — the CLI uses built-in defaults. + +To create a default config: + +```bash +te config init # Create ~/.config/te/config.json with defaults +te config init --force # Overwrite existing config +``` + +## Viewing configuration + +```bash +te config show # Display all settings +te config show --output json # Machine-readable +te config paths # Show resolved TE3 file paths +``` + +`te config paths` resolves where the CLI will actually look for TE3 data files — useful when debugging missing macros or BPA rules. + +## Setting values + +```bash +te config set autoFormat true +te config set bpaOnDeploy false +te config set hidePreviewNotice true +te config set macros null # Clear a path override +``` + +Unknown keys fail with an error that lists the valid keys. + +## Full schema + +```json +{ + "te3DataDir": null, + "preferences": null, + "macros": null, + "bpaRules": null, + "bpaMachineRules": null, + + "autoFormat": false, + "validateOnMutation": true, + "bpaOnMutation": false, + "bpaOnDeploy": true, + "bpaOnSave": true, + "vertipaqOnRefresh": false, + + "formatOptions": { + "useSemicolons": false, + "shortFormat": false, + "skipSpaceAfterFunction": false + }, + + "hidePreviewNotice": false, + "spinner": true, + "debug": false, + + "profiles": {} +} +``` + +### Path overrides + +| Key | Meaning | +| -- | -- | +| `te3DataDir` | Base directory used for TE3 file discovery when individual paths below are not set. Defaults to `%LOCALAPPDATA%\TabularEditor3` (Windows) or the equivalent auto-detected location on macOS/Linux. | +| `preferences` | Explicit path to `Preferences.json`. | +| `macros` | Explicit path to `MacroActions.json`. | +| `bpaRules` | Explicit path to user-level `BPARules.json`. | +| `bpaMachineRules` | Explicit path to machine-level `BPARules.json`. | + +### Path resolution priority + +For each TE3 file (Preferences, macros, BPA rules), the CLI resolves the path in this order: + +1. **CLI config override** — the explicit entry above (`preferences`, `macros`, …). +2. **Environment variable** — e.g., `TE_MACROS_PATH`, `TE_BPA_RULES_PATH`. +3. **`te3DataDir`** — joined with the default filename. +4. **Auto-detect** — Windows `%LOCALAPPDATA%\TabularEditor3\...`, or the equivalent on macOS/Linux; on macOS we also probe a Parallels-style mapping if present. + +Run `te config paths` to see which file the CLI actually resolved for each TE3 asset. + +### Behavioral defaults + +| Key | Default | Description | +| -- | -- | -- | +| `autoFormat` | `false` | Run DAX Formatter on modified expressions after `te add` / `te set` / `te mv` / `te macro run`. | +| `validateOnMutation` | `true` | Validate `Table[Column]` references after any mutating command. | +| `bpaOnMutation` | `false` | Run BPA after mutating commands. | +| `bpaOnDeploy` | `true` | Run BPA as a gate before `te deploy`. Bypass with `--skip-bpa`. | +| `bpaOnSave` | `true` | Run BPA as a gate before `te save`. Bypass with `--skip-bpa`. | +| `vertipaqOnRefresh` | `false` | Capture VertiPaq stats after a successful refresh. | + +### Format options + +Applied whenever the CLI invokes the DAX Formatter (for `te format` and, when enabled, `autoFormat` on mutations). + +| Key | Default | Description | +| -- | -- | -- | +| `formatOptions.useSemicolons` | `false` | Use `;` as the list separator (European locale). | +| `formatOptions.shortFormat` | `false` | Use the compact layout variant. | +| `formatOptions.skipSpaceAfterFunction` | `false` | Omit the space between a function name and its opening parenthesis. | + +### Display + +| Key | Default | Description | +| -- | -- | -- | +| `hidePreviewNotice` | `false` | Suppress the yellow preview banner. **Ignored within 14 days of expiry.** | +| `spinner` | `true` | Show animated progress indicators in the terminal. Disable for CI. | +| `debug` | `false` | Always enable debug logging (same as passing `--debug`). | + +### Profiles + +Saved connection profiles live under the `profiles` key. Don't edit them by hand — use `te profile set / remove / list`. See @te-cli-auth for profile management. + +Profiles can carry **overrides** that override the behavioral defaults above whenever the profile is active. This is how a dev profile can relax validation and BPA while a prod profile keeps them strict: + +```bash +te profile set dev --validate-on-mutation false --bpa-on-deploy false +te profile set prod --auto-format true +``` + +## BPA gate + +The BPA gate is the safety net that prevents a model with rule violations from being saved or deployed. It runs automatically when: + +- `te deploy` executes — unless `--skip-bpa` is passed or `bpaOnDeploy` is `false`. +- `te save` executes — unless `--skip-bpa` is passed or `bpaOnSave` is `false`. +- `te add` / `te set` / `te mv` / `te macro run` executes — only when `bpaOnMutation` is `true`. + +When the gate fires and finds violations at severity ≥ `error`, the command fails with exit code `1` and a summary of the violations. Options to resolve: + +- `--fix-bpa` — apply the rule's `fixExpression` in memory for the deploy/save artifact; source files are not modified. +- `--skip-bpa` — disable the gate for this one command. +- `.te-bpa.json` in the model directory — project-local BPA gate configuration (replacement for editing Preferences). + +Run `te bpa run` independently to preview the gate's behavior without deploying: + +```bash +te bpa run ./model --fail-on error +te bpa run ./model --fix --save # Apply fixes to the source +``` + +## Post-mutation behavior + +When you run a mutating command (`te add`, `te set`, `te mv`, `te replace --save`, `te macro run`), the CLI performs these checks automatically: + +1. **TOM errors** are always surfaced — invalid DAX or M in measures, columns, partitions, calculation items. These always fail the command. +2. **Schema validation** (`validateOnMutation`, default `true`) — verifies that `Table[Column]` references in DAX still resolve. Cross-check of metadata consistency. +3. **DAX auto-format** (`autoFormat`, default `false`) — when enabled, formats any expressions touched by the mutation via the built-in DAX Formatter. +4. **BPA on mutation** (`bpaOnMutation`, default `false`) — when enabled, runs BPA after the mutation and warns/fails based on `--fail-on`. + +Disable a check with `te config set false`, or scope the relaxation to a specific environment via a profile. + +## Environment variables + +| Variable | Purpose | +| -- | -- | +| `TE_CONFIG` | Path to an alternative config file. Overrides `~/.config/te/config.json`. | +| `TE_DEBUG` | Set to `1` to enable debug logging globally (same as `--debug` or `debug: true` in config). | +| `TE_COMPAT` | Set to `te2` to force TE2-compatibility mode — see @te-cli-migrate. | +| `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID` | Service principal credentials, used by `--auth env`. | +| `TE_MACROS_PATH`, `TE_BPA_RULES_PATH`, ... | Per-file overrides for TE3 asset paths (second in resolution order — see above). | + +## Related pages + +- @te-cli-auth — profiles, authentication, and credential storage. +- @te-cli-commands — `te config` subcommands. +- @te-cli-cicd — configuring the BPA gate for pipelines. diff --git a/content/features/te-cli/te-cli-install.md b/content/features/te-cli/te-cli-install.md new file mode 100644 index 000000000..96e78ced6 --- /dev/null +++ b/content/features/te-cli/te-cli-install.md @@ -0,0 +1,150 @@ +--- +uid: te-cli-install +title: Installation and Setup +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Installation and Setup + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +The Tabular Editor CLI ships as a single self-contained executable named `te` (`te.exe` on Windows). It has no external runtime dependencies. + +## Download + +1. Sign in at [tabulareditor.com](https://tabulareditor.com) with a Tabular Editor account. +2. Download the archive for your platform and architecture: + + | Platform | 64-bit (Intel/AMD) | ARM64 | + | -- | -- | -- | + | Windows | `win-x64` | `win-arm64` | + | macOS | `osx-x64` (Intel) | `osx-arm64` (Apple Silicon) | + | Linux | `linux-x64` | `linux-arm64` | + + Pick the ARM64 build on Apple Silicon Macs (M1 and newer), Windows on ARM devices, and ARM-based Linux servers (including AWS Graviton, Azure Ampere, and Raspberry Pi 64-bit). Pick the `x64` build on everything else. + + + +## Install + +Unzip the archive into a folder of your choice and add that folder to `PATH` so you can invoke `te` from any working directory. + +### Windows (PowerShell) + +```powershell +# Substitute te-win-x64.zip or te-win-arm64.zip depending on your machine. +Expand-Archive te-win-x64.zip -DestinationPath "$env:LOCALAPPDATA\Programs\te" + +# Add to PATH (current user, persistent) +[Environment]::SetEnvironmentVariable( + "PATH", + [Environment]::GetEnvironmentVariable("PATH", "User") + ";$env:LOCALAPPDATA\Programs\te", + "User") +``` + +Restart the terminal for the PATH change to take effect. + +### macOS / Linux + +```bash +# Substitute the archive that matches your platform/arch: +# macOS Apple Silicon: te-osx-arm64.zip +# macOS Intel: te-osx-x64.zip +# Linux x64: te-linux-x64.zip +# Linux ARM64: te-linux-arm64.zip +mkdir -p ~/.local/bin +unzip te-osx-arm64.zip -d ~/.local/bin +chmod +x ~/.local/bin/te + +# Ensure ~/.local/bin is on PATH +echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # or ~/.bashrc +``` + +On macOS, the first run may trigger a Gatekeeper quarantine warning. Remove the quarantine attribute with: + +```bash +xattr -d com.apple.quarantine ~/.local/bin/te +``` + +## Verify + +Check the installed version and list available commands: + +```bash +te --version +te --help +``` + +`te --help` prints a colorized help index grouping commands by family. Every subcommand accepts `--help` for detailed usage: + +```bash +te deploy --help +te bpa run --help +``` + +## Hide the preview banner + +The CLI prints a yellow preview banner on stderr by default. To suppress it for routine commands: + +```bash +te config set hidePreviewNotice true +``` + +> [!WARNING] +> The banner reappears on every command within **14 days of expiry** (2026-09-30), regardless of `hidePreviewNotice`. This ensures you have visible warning before the CLI stops functioning. + +## Shell completion + +Generate a shell completion script for your shell of choice: + +```bash +te completion bash > /etc/bash_completion.d/te +te completion zsh > "${fpath[1]}/_te" +te completion pwsh | Out-String | Invoke-Expression +``` + +Completion covers subcommands, global flags, and model paths (where tab-completion against the filesystem is meaningful). + +## Cross-platform feature matrix + +Most features are identical across platforms. A handful depend on Windows-only transports: + +| Feature | Windows | macOS / Linux | +| -- | -- | -- | +| Load/save BIM and TMDL | Yes | Yes | +| Deploy to Power BI / Fabric / Azure Analysis Services | Yes | Yes | +| Best Practice Analyzer and VertiPaq Analyzer | Yes | Yes | +| C# scripting | Yes | Yes | +| DAX queries against cloud models | Yes | Yes | +| Auth: browser, device-code, service principal, env, managed identity | Yes | Yes | +| Connect to local SSAS instance (TCP transport) | Yes | No | +| Connect to Power BI Desktop (named-pipe transport) | Yes | No | + +Local SSAS and Power BI Desktop connections rely on Windows-only transport protocols. All cloud-based workflows (Power BI Service, Fabric, Azure Analysis Services) work on every platform. + +## Updating + +To update to a newer preview build, download the latest archive and overwrite the previous installation. Configuration and cached credentials are stored outside the install folder (see @te-cli-config and @te-cli-auth) and are preserved across updates. + +## Uninstalling + +1. Delete the install folder. +2. Remove the PATH entry. +3. (Optional) Clear cached credentials and config: + - Windows / Linux: `~/.te-cli/`, `~/.config/te/` + - macOS: `~/.te-cli/token-cache.bin`, `~/.config/te/` + +## Next steps + +- @te-cli-auth — authenticate to Power BI, Fabric, or Azure Analysis Services. +- @te-cli-commands — full command reference. +- @te-cli-interactive — guided REPL mode. diff --git a/content/features/te-cli/te-cli-interactive.md b/content/features/te-cli/te-cli-interactive.md new file mode 100644 index 000000000..061673130 --- /dev/null +++ b/content/features/te-cli/te-cli-interactive.md @@ -0,0 +1,83 @@ +--- +uid: te-cli-interactive +title: Interactive Mode +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Interactive Mode + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +Interactive mode is a guided REPL (read-eval-print loop) for exploring a model from the terminal. It's the gentlest on-ramp for users who are new to command lines, and a convenient workspace for ad-hoc sessions against a single model. + +## Starting a session + +```bash +te interactive # Start and connect to a model later +te interactive ./model # Start with a local model +te interactive -s MyWorkspace -d MyModel # Start with a remote model +``` + +The session prints a welcome banner, shows the active model, and drops you at a model-aware prompt: + +``` +te [MyModel]> +``` + +If no model is set, the prompt is just `te>` — use `connect ` or `connect ` inside the session to bind one. + +## Commands inside the session + +Every `te` subcommand is available **without the `te` prefix**: + +``` +te [MyModel]> ls tables +te [MyModel]> get "Sales/Revenue" -q expression +te [MyModel]> query -q "EVALUATE TOPN(5, 'Sales')" +te [MyModel]> bpa run --fail-on error +``` + +Each command accepts `--help` the same way it does outside the session: + +``` +te [MyModel]> deploy --help +``` + +## Built-in REPL commands + +These are handled by the REPL itself, not the regular command tree: + +| Command | Purpose | +| -- | -- | +| `help` or `?` | List available commands. | +| `status` or `pwd` | Show the active model/connection. | +| `clear` or `cls` | Clear the screen. | +| `exit`, `quit`, or `q` | Exit interactive mode. | + +## Guided prompts + +When interactive mode is active, commands that need missing input prompt for it instead of failing. Running `auth` without a subcommand opens a picker for Login / Status / Logout; running `deploy` without `--force` shows a summary and asks for confirmation (`n` is the safe default). + +To disable prompts for a single command inside the session, pass `--non-interactive`. + +## When to use interactive vs. non-interactive + +- **Interactive mode** is best for exploration, learning the CLI, one-off bulk edits against a single model, and demos. +- **Non-interactive mode** (the default outside `te interactive`) is what you reach for when scripting, automating, or running in CI. See @te-cli-automation and @te-cli-cicd. + +The two share the same command tree — anything you run inside `te interactive` can be pasted into a shell script by prefixing it with `te`. + +## Related pages + +- @te-cli-commands — full command reference. +- @te-cli-auth — connect to workspaces and manage profiles. +- @te-cli-automation — when to leave interactive mode. diff --git a/content/features/te-cli/te-cli-migrate.md b/content/features/te-cli/te-cli-migrate.md new file mode 100644 index 000000000..288fba42d --- /dev/null +++ b/content/features/te-cli/te-cli-migrate.md @@ -0,0 +1,111 @@ +--- +uid: te-cli-migrate +title: Migrating from the TE2 Command Line +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Migrating from the TE2 Command Line + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +Teams with existing build pipelines that invoke `TabularEditor.exe` with TE2-style flags (`-S`, `-A`, `-D`, `-O`, `-C`, etc.) can adopt the new CLI incrementally. The Tabular Editor CLI accepts both command shapes: the new subcommand-based form (`te deploy`, `te bpa run`, …) and the legacy TE2 flag syntax, via a built-in compatibility layer. + +For the legacy TE2 Windows command-line reference, see @command-line-options. + +## How TE2 compatibility works + +TE2 compatibility mode is activated in any of three ways: + +1. **Binary name.** Rename `te` to `te2` (or symlink it) and the CLI runs in TE2-exact mode. This is the drop-in replacement path: swap `TabularEditor.exe` for `te2` in your existing pipeline and the same arguments work. +2. **Environment variable.** Set `TE_COMPAT=te2` before invoking `te` to force TE2 mode. +3. **Auto-detection.** If the first argument isn't a `te` subcommand (`load`, `deploy`, …) and at least one recognized TE2 flag appears somewhere in the argument list, the CLI auto-routes to TE2 mode. This means most existing TE2 invocations work without any changes. + +```bash +# All three are equivalent — each runs in TE2 mode +./te2 Model.bim -S fix.csx -D localhost\tabular MyDB -O +TE_COMPAT=te2 te Model.bim -S fix.csx -D localhost\tabular MyDB -O +te Model.bim -S fix.csx -D localhost\tabular MyDB -O +``` + +> [!NOTE] +> TE2 mode runs the same `Load → Scripts → Schema Check → Save → BPA → Deploy → TRX` pipeline as `TabularEditor.exe`, including context-sensitive flag behavior (e.g., `-S` after `-D` means `-SHARED`, not `-SCRIPT`). + +## The migrate command + +Use `te migrate` as a live reference for how TE2 flags map to the new CLI. It prints a colorized table of every known TE2 flag, its status (supported, renamed, planned), and the equivalent `te` command. + +```bash +te migrate # Full flag mapping table +te migrate -A # Look up a single flag +te migrate --output json # Machine-readable mapping +``` + +Prefer `te migrate` over this page when you need the current mapping — it reflects the CLI version you have installed. + +## Flag mapping (curated subset) + +A non-exhaustive summary of the most commonly used flags. Run `te migrate` for the full list. + +| TE2 flag | New CLI equivalent | Notes | +| -- | -- | -- | +| `file` (positional) | `te ` or global `--model` | First positional arg on most commands. | +| `server`, `database` | `te connect ` or `te deploy ` | Server is no longer a global positional. | +| `-L` / `-LOCAL` | `te connect --local` | Windows only. | +| `-S` / `-SCRIPT` | `te script -s ` or `-e "code"` | Supports multiple scripts, inline code, and stdin. | +| `-A` / `-ANALYZE` | `te bpa run --rules ` | Supports `--fail-on`, `--fix`, multiple rule files. | +| `-AX` / `-ANALYZEX` | `te bpa run --rules ` (without `--model-rules`) | Excluding model-embedded rules is the new default. | +| `-B` / `-BIM` | `te save -o --format bim` | | +| `-F` / `-FOLDER` | `te save -o --format te-folder` | After `-D`, TE2's `-F` means `-FULL` — see `--deploy-full`. | +| `-TMDL` | `te save -o --format tmdl` | TMDL is the default save format. | +| `-D` / `-DEPLOY` | `te deploy ` | Separate command with named options. | +| `-O` / `-OVERWRITE` | (default) or `--create-only` to opt out | Overwrite is the default in the new CLI. | +| `-C` / `-CONNECTIONS` | `te deploy --deploy-connections` | | +| `-P` / `-PARTITIONS` | `te deploy --deploy-partitions` | | +| `-Y` / `-SKIPPOLICY` | `te deploy --deploy-partitions --skip-refresh-policy` | Requires `--deploy-partitions`. | +| `-SHARED` | `te deploy --deploy-shared-expressions` | After `-D`, TE2's `-S` means `-SHARED`. | +| `-R` / `-ROLES` | `te deploy --deploy-roles` | | +| `-M` / `-MEMBERS` | `te deploy --deploy-role-members` | | +| `-FULL` (after `-D`) | `te deploy --deploy-full` | Equivalent to overwrite + connections + partitions + shared + roles + role-members. | +| `-X` / `-XMLA ` | `te deploy ... --xmla ` | Use `-` for stdout. | +| `-V` / `-VSTS` | `--ci vsts` on `validate`, `bpa run`, `deploy` | Emits `##vso[...]` annotations to stderr. | +| `-G` / `-GITHUB` | `--ci github` | Emits `::error::` / `::warning::` annotations. | +| `-T` / `-TRX ` | `--trx ` on `validate`, `bpa run`, `test run` | VSTEST `.trx` file for Azure DevOps test publishing. | +| `-W` / `-WARN` | (default) | Warnings always reported in deploy results. | +| `-E` / `-ERR` | (default) | Deploy returns non-zero exit on DAX errors. | +| `-SC` / `-SCHEMACHECK` | *Not yet implemented.* | TE2 schema check connects to actual data sources. Different from `te validate` (DAX semantic validation, no data source connection). | +| `-L` / `-LOGIN ` (after `-D`) | *Not yet implemented.* | Use `te auth login` with service principal or env-based credentials instead — see @te-cli-auth. | + +## Migration playbook + +The recommended path from a TE2-based pipeline to the new CLI: + +1. **Drop-in replacement.** Replace `TabularEditor.exe` with `te` (or `te2`) in your existing pipeline. Verify the pipeline still runs — TE2 compatibility handles most invocations unchanged. +2. **Replace flags incrementally.** Convert one flag group at a time: + - Start with `-A` / `-AX` → `te bpa run` to pick up richer BPA output (`--fail-on`, `--fix`, `--trx`). + - Then `-D` → `te deploy` for fine-grained deploy control. + - Finally `-V` / `-G` → `--ci vsts` / `--ci github`. +3. **Switch to non-interactive CI flags.** Add `--non-interactive --ci ` to every `te` command and remove any `start /wait` wrappers — the new CLI is a regular console binary and doesn't need them. +4. **Adopt service principal auth.** Replace `-D -L ` with `te auth login -u ... -p ... -t ...` or an environment-credential pipeline step. See @te-cli-auth. + +## Differences worth knowing + +- **BPA gate on deploy.** `te deploy` now runs BPA as a pre-flight gate by default. Use `--skip-bpa` to preserve the old behavior, or `--fix-bpa` to auto-fix violations before deploy. See @te-cli-config. +- **Interactive confirmation on deploy.** `te deploy` prompts for confirmation by default (with `n` as the safe default answer). CI pipelines must pass `--force`. +- **Structured output.** Every command supports `--output json` for machine-readable output — see @te-cli-automation. +- **No `start /wait` needed.** The new CLI is a regular console binary; invoke it directly in shell scripts, PowerShell, and CI tasks. +- **Cross-platform.** The CLI runs on Windows, macOS, and Linux. Local SSAS and Power BI Desktop connections remain Windows-only. + +## Related pages + +- @command-line-options — the legacy TE2 command-line reference. +- @te-cli-commands — the new CLI's full command reference. +- @te-cli-cicd — pipeline examples for GitHub Actions and Azure DevOps. diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md new file mode 100644 index 000000000..093d388c3 --- /dev/null +++ b/content/features/te-cli/te-cli.md @@ -0,0 +1,95 @@ +--- +uid: te-cli +title: Tabular Editor CLI (Limited Public Preview) +author: Peer Grønnerup +updated: 2026-04-20 +applies_to: + products: + - product: Tabular Editor 2 + none: true + - product: Tabular Editor 3 + none: true + - product: Tabular Editor CLI + full: true +--- +# Tabular Editor CLI (Limited Public Preview) + +The Tabular Editor CLI (`te`) is a cross-platform command-line interface for Power BI and Analysis Services semantic models. It runs on Windows, macOS, and Linux as a single self-contained executable and wraps the same model engine (TOMWrapper) that powers Tabular Editor 3 Desktop. + +Use it to inspect, edit, validate, deploy, refresh, and test semantic models from a terminal — against local TMDL or BIM files, Power BI Desktop, or semantic models in Fabric and Power BI Service workspaces. + +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. + +## Built for three audiences + +The CLI was designed to serve three consumers from the same binary: + +- **Humans** — scripting bulk edits, exploring a model from the terminal, composing commands in shell pipelines. +- **AI agents** — token-lean structured output, predictable exit codes, machine-parseable errors. +- **CI/CD pipelines** — non-interactive mode, GitHub Actions and Azure DevOps annotations, VSTEST-compatible test results. + +The same design choices — structured JSON output, a `--non-interactive` global flag, clear errors — serve all three. + +## What the CLI can do + +The CLI organizes more than 50 commands into 10 families. Each family maps to a concrete stage of the semantic-model lifecycle. + +| Family | What it does | Example commands | +| -- | -- | -- | +| Model I/O | Load, save, export, initialize models | `te load`, `te save`, `te export` | +| Model Editing | Get/set properties, add/remove/move objects | `te set`, `te add`, `te rm`, `te mv` | +| Inspection | List objects, search, diff, dependency analysis | `te ls`, `te find`, `te diff`, `te deps` | +| Analysis & Quality | Validate, run BPA, format DAX, analyze storage | `te validate`, `te bpa run`, `te format`, `te vertipaq` | +| Execution | Run DAX queries, C# scripts, macros | `te query`, `te script`, `te macro` | +| Deployment & Refresh | Deploy to workspace, trigger refresh, incremental refresh | `te deploy`, `te refresh`, `te incremental-refresh` | +| Testing | Assertion tests, snapshots, A/B comparison | `te test run` | +| Connection & Auth | Connect to workspaces, manage authentication and profiles | `te connect`, `te auth`, `te profile` | +| Configuration | Settings and licensing | `te config`, `te license` | +| Shell | Interactive mode, shell completions | `te interactive`, `te completion` | + +See @te-cli-commands for a full command reference with syntax, options, and examples for each command. + +## Getting started + +1. **Sign up or sign in** at [tabulareditor.com](https://tabulareditor.com) with a Tabular Editor account. +2. **Download and install** — see @te-cli-install for Windows, macOS, and Linux instructions. +3. **Authenticate** — run `te auth login` to connect to Power BI or Fabric. See @te-cli-auth. +4. **Run your first command** — `te --help` lists every command; `te --help` shows detailed options. + +A first look at a live model takes two commands: + +```bash +te auth login +te ls -s MyWorkspace -d MyModel +``` + +## Preview notice + +Every command prints a yellow preview banner on stderr by default. To quiet it down: + +```bash +te config set hidePreviewNotice true +``` + +The banner **always** reappears within 14 days of the expiry date (2026-09-30), regardless of this setting, to give you a clear runway to update. + +## License outlook + +During Limited Public Preview, the CLI does not require a license; you only need a Tabular Editor account to download it. At general availability the CLI will require a license; pricing is still being finalized and will be announced ahead of GA. + + + +## Next steps + +- @te-cli-install — download, install, verify. +- @te-cli-auth — authenticate to Power BI, Fabric, and Azure Analysis Services. +- @te-cli-commands — full command reference. +- @te-cli-config — configuration file and path overrides. +- @te-cli-interactive — guided REPL mode for new users. +- @te-cli-automation — structured output, scripting patterns for Python, PowerShell, and Bash. +- @te-cli-cicd — GitHub Actions and Azure DevOps pipeline examples. +- @te-cli-migrate — migrating from the Tabular Editor 2 command line. + + + diff --git a/content/features/toc.md b/content/features/toc.md index 5cdcc4685..e46f3b476 100644 --- a/content/features/toc.md +++ b/content/features/toc.md @@ -63,6 +63,15 @@ # Command Line and Integration ## @command-line-options +## [Tabular Editor CLI (Limited PuPr)](xref:te-cli) +### @te-cli-install +### @te-cli-auth +### @te-cli-commands +### @te-cli-config +### @te-cli-interactive +### @te-cli-automation +### @te-cli-cicd +### @te-cli-migrate # Semantic Bridge for cross-platform translations ## @semantic-bridge diff --git a/docfx.json b/docfx.json new file mode 100644 index 000000000..6e52c0d5c --- /dev/null +++ b/docfx.json @@ -0,0 +1,940 @@ +{ + "rules": { + "InvalidAssemblyReference": "Suggestion", + "EmptyTocItemName": "Suggestion" + }, + "metadata": [ + { + "src": [ + { + "files": [ + "content/_apiSource/*.dll" + ] + } + ], + "dest": "content/api", + "filter": "configuration/filterConfig.yml" + } + ], + "build": { + "content": [ + { + "files": "**/*.md", + "src": "content/features", + "dest": "features" + }, + { + "files": "**/*.md", + "src": "content/getting-started", + "dest": "getting-started" + }, + { + "files": "**/*.md", + "src": "content/how-tos", + "dest": "how-tos" + }, + { + "files": "**/*.md", + "src": "content/references", + "dest": "references" + }, + { + "files": "**/*.md", + "src": "content/kb", + "dest": "kb" + }, + { + "files": "**/*.md", + "src": "content/security", + "dest": "security" + }, + { + "files": "**/*.md", + "src": "content/troubleshooting", + "dest": "troubleshooting" + }, + { + "files": "**/*.md", + "src": "content/tutorials", + "dest": "tutorials" + }, + { + "files": "*.md", + "src": "content" + }, + { + "files": "toc.yml", + "src": "content" + }, + { + "files": "*", + "src": "content/api", + "dest": "api" + }, + { + "files": "common/CSharpScripts/Advanced/script-add-databricks-metadata-descriptions.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-convert-dlsql-to-dlol.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-convert-import-to-dlol.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-count-things.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-create-and-replace-M-parameter.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-create-databricks-relationships.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-create-date-table.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-databricks-semantic-model-set-up.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-find-replace-selected-measures.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-format-power-query.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-implement-incremental-refresh.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-output-things.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Advanced/script-remove-measures-with-error.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-count-rows.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-create-field-parameter.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-create-m-parameter.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-create-measure-table.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-create-sum-measures-from-columns.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-create-table-groups.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-display-unique-column-values.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-edit-hidden-partitions.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-format-numeric-measures.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Beginner/script-show-data-source-dependencies.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/Template/csharp-script-Template.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/csharp-script-library-advanced.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/csharp-script-library-beginner.md", + "src": "content" + }, + { + "files": "common/CSharpScripts/csharp-script-library.md", + "src": "content" + }, + { + "files": "common/Semantic Model/direct-lake-sql-model.md", + "src": "content" + }, + { + "files": "common/Semantic Model/direct-query-over-as.md", + "src": "content" + }, + { + "files": "common/Semantic Model/semantic-model-types.md", + "src": "content" + }, + { + "files": "common/desktop-limitations.md", + "src": "content" + }, + { + "files": "common/policies.md", + "src": "content" + }, + { + "files": "common/save-to-folder.md", + "src": "content" + }, + { + "files": "common/script-helper-methods.md", + "src": "content" + }, + { + "files": "common/using-bpa-sample-rules-expressions.md", + "src": "content" + }, + { + "files": "common/xmla-as-connectivity.md", + "src": "content" + }, + { + "files": "onboarding/as-cicd.md", + "src": "content" + }, + { + "files": "onboarding/boosting-productivity-te3.md", + "src": "content" + }, + { + "files": "onboarding/bpa.md", + "src": "content" + }, + { + "files": "onboarding/creating-and-testing-dax.md", + "src": "content" + }, + { + "files": "onboarding/cs-scripts-and-macros.md", + "src": "content" + }, + { + "files": "onboarding/dax-script-introduction.md", + "src": "content" + }, + { + "files": "onboarding/general-introduction.md", + "src": "content" + }, + { + "files": "onboarding/importing-tables-data-modeling.md", + "src": "content" + }, + { + "files": "onboarding/index.md", + "src": "content" + }, + { + "files": "onboarding/installation.md", + "src": "content" + }, + { + "files": "onboarding/migrate-from-desktop.md", + "src": "content" + }, + { + "files": "onboarding/migrate-from-te2.md", + "src": "content" + }, + { + "files": "onboarding/migrate-from-vs.md", + "src": "content" + }, + { + "files": "onboarding/parallel-development.md", + "src": "content" + }, + { + "files": "onboarding/personalizing-te3.md", + "src": "content" + }, + { + "files": "onboarding/powerbi-cicd.md", + "src": "content" + }, + { + "files": "onboarding/refresh-preview-query.md", + "src": "content" + }, + { + "files": "te2/Advanced-Filtering-of-the-Explorer-Tree.md", + "src": "content" + }, + { + "files": "te2/Advanced-Scripting.md", + "src": "content" + }, + { + "files": "te2/Best-Practice-Analyzer-Improvements.md", + "src": "content" + }, + { + "files": "te2/Command-line-Options.md", + "src": "content" + }, + { + "files": "te2/Custom-Actions.md", + "src": "content" + }, + { + "files": "te2/FAQ.md", + "src": "content" + }, + { + "files": "te2/FormatDax.md", + "src": "content" + }, + { + "files": "te2/Getting-Started.md", + "src": "content" + }, + { + "files": "te2/Importing-Tables.md", + "src": "content" + }, + { + "files": "te2/Keyboard-Shortcuts.md", + "src": "content" + }, + { + "files": "te2/Maintaining-Calculations-using-Scripting.md", + "src": "content" + }, + { + "files": "te2/Master-model-pattern.md", + "src": "content" + }, + { + "files": "te2/Roadmap.md", + "src": "content" + }, + { + "files": "te2/SQL-Server-2017-support.md", + "src": "content" + }, + { + "files": "te2/TabularEditor.TOMWrapper.md", + "src": "content" + }, + { + "files": "te2/Useful-script-snippets.md", + "src": "content" + }, + { + "files": "te2/Workspace-Database.md", + "src": "content" + }, + { + "files": "te2/gdpr-delete.md", + "src": "content" + }, + { + "files": "te2/importing-tables-from-excel.md", + "src": "content" + }, + { + "files": "te2/incremental-refresh.md", + "src": "content" + }, + { + "files": "te3/azure-marketplace.md", + "src": "content" + }, + { + "files": "te3/editions.md", + "src": "content" + }, + { + "files": "te3/features/code-actions.md", + "src": "content" + }, + { + "files": "te3/features/csharp-scripts.md", + "src": "content" + }, + { + "files": "te3/features/dax-debugger.md", + "src": "content" + }, + { + "files": "te3/features/dax-editor.md", + "src": "content" + }, + { + "files": "te3/features/dax-optimizer-integration.md", + "src": "content" + }, + { + "files": "te3/features/dax-package-manager.md", + "src": "content" + }, + { + "files": "te3/features/dax-query.md", + "src": "content" + }, + { + "files": "te3/features/dax-scripts.md", + "src": "content" + }, + { + "files": "te3/features/deployment.md", + "src": "content" + }, + { + "files": "te3/features/diagram-view.md", + "src": "content" + }, + { + "files": "te3/features/metadata-translation-editor.md", + "src": "content" + }, + { + "files": "te3/features/perspective-editor.md", + "src": "content" + }, + { + "files": "te3/features/pivot-grid.md", + "src": "content" + }, + { + "files": "te3/features/preferences.md", + "src": "content" + }, + { + "files": "te3/features/security-privacy.md", + "src": "content" + }, + { + "files": "te3/features/shortcuts.md", + "src": "content" + }, + { + "files": "te3/features/supported-files.md", + "src": "content" + }, + { + "files": "te3/features/table-groups.md", + "src": "content" + }, + { + "files": "te3/features/tmdl.md", + "src": "content" + }, + { + "files": "te3/features/user-options.md", + "src": "content" + }, + { + "files": "te3/getting-started.md", + "src": "content" + }, + { + "files": "te3/import-tables.partial.md", + "src": "content" + }, + { + "files": "te3/index.md", + "src": "content" + }, + { + "files": "te3/other/downloads.md", + "src": "content" + }, + { + "files": "te3/other/privacy-policy.md", + "src": "content" + }, + { + "files": "te3/other/release-history.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_10.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_3.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_4.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_5.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_6.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_7.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_8.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_0_9.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_10_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_10_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_11_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_12_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_12_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_13_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_14_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_15_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_16_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_16_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_16_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_17_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_17_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_18_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_18_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_18_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_19_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_3.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_4.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_5.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_6.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_1_7.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_20_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_20_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_21_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_22_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_22_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_23_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_23_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_24_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_24_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_24_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_2_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_2_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_2_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_2_3.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_3.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_4.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_5.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_3_6.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_4_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_4_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_4_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_5_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_5_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_6_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_7_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_7_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_8_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/3_9_0.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-16_6.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-17_4.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-18_1.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-18_2.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-18_3.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-18_4.md", + "src": "content" + }, + { + "files": "te3/other/release-notes/beta-18_5.md", + "src": "content" + }, + { + "files": "te3/other/roadmap.md", + "src": "content" + }, + { + "files": "te3/other/third-party-notices.md", + "src": "content" + }, + { + "files": "te3/powerbi-xmla-pbix-workaround.md", + "src": "content" + }, + { + "files": "te3/powerbi-xmla.md", + "src": "content" + }, + { + "files": "te3/proxy-settings.md", + "src": "content" + }, + { + "files": "te3/troubleshooting/calendar-blank-value.md", + "src": "content" + }, + { + "files": "te3/troubleshooting/direct-lake-entity-updates-reverting.md", + "src": "content" + }, + { + "files": "te3/troubleshooting/locale-not-supported.md", + "src": "content" + }, + { + "files": "te3/tutorials/calendars.md", + "src": "content" + }, + { + "files": "te3/tutorials/connecting-to-azure-databricks.md", + "src": "content" + }, + { + "files": "te3/tutorials/creating-macros.md", + "src": "content" + }, + { + "files": "te3/tutorials/data-security/data-security-about.md", + "src": "content" + }, + { + "files": "te3/tutorials/data-security/data-security-setup-ols.md", + "src": "content" + }, + { + "files": "te3/tutorials/data-security/data-security-setup-rls.md", + "src": "content" + }, + { + "files": "te3/tutorials/data-security/data-security-testing.md", + "src": "content" + }, + { + "files": "te3/tutorials/direct-lake-guidance.md", + "src": "content" + }, + { + "files": "te3/tutorials/incremental-refresh/incremental-refresh-about.md", + "src": "content" + }, + { + "files": "te3/tutorials/incremental-refresh/incremental-refresh-modify.md", + "src": "content" + }, + { + "files": "te3/tutorials/incremental-refresh/incremental-refresh-schema.md", + "src": "content" + }, + { + "files": "te3/tutorials/incremental-refresh/incremental-refresh-setup.md", + "src": "content" + }, + { + "files": "te3/tutorials/incremental-refresh/incremental-refresh-workspace-mode.md", + "src": "content" + }, + { + "files": "te3/tutorials/new-as-model.md", + "src": "content" + }, + { + "files": "te3/tutorials/new-pbi-model.md", + "src": "content" + }, + { + "files": "te3/tutorials/udfs.md", + "src": "content" + }, + { + "files": "te3/views/data-refresh-view.md", + "src": "content" + }, + { + "files": "te3/views/find-replace.md", + "src": "content" + }, + { + "files": "te3/views/macros-view.md", + "src": "content" + }, + { + "files": "te3/views/messages-view.md", + "src": "content" + }, + { + "files": "te3/views/properties-view.md", + "src": "content" + }, + { + "files": "te3/views/tom-explorer-view.md", + "src": "content" + }, + { + "files": "te3/views/user-interface.md", + "src": "content" + }, + { + "files": "te3/whats-new.md", + "src": "content" + }, + { + "files": "te3/workspace-mode.partial.md", + "src": "content" + }, + { + "files": "te3/tutorials/workspace-mode.md", + "src": "content" + } + ], + "template": [ + "default", + "templates/tabulareditor" + ], + "resource": [ + { + "files": "**", + "src": "content/assets/images", + "dest": "images" + }, + { + "files": "**", + "src": "content/whats-new", + "dest": "whats-new" + }, + { + "files": "*.html", + "src": "content" + } + ], + "globalMetadata": { + "_appTitle": "Tabular Editor Documentation", + "_enableSearch": true, + "_enableNewTab": true, + "_disableNavbar": true, + "_disableContribution": true + }, + "markdownEngineName": "markdig", + "dest": "_site", + "xrefService": [ + "https://xref.docs.microsoft.com/query?uid={uid}" + ] + } +} \ No newline at end of file From 60a727c0e10137253f76f101905b38cb99d3f4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Gr=C3=B8nnerup?= <52330973+gronnerup@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:08:36 +0200 Subject: [PATCH 2/9] Delete .claude/settings.local.json --- .claude/settings.local.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index bee240cf6..000000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "permissions": { - "allow": [ - "WebFetch(domain:tabulareditor.com)" - ] - } -} From 8ab7a677ef7b1cb956d174d118d5bb49ff79be8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Gr=C3=B8nnerup?= Date: Wed, 22 Apr 2026 08:41:53 +0200 Subject: [PATCH 3/9] Added link to the GitHub repo for issues and discussions. Updated gitignore. --- .gitignore | 2 +- content/features/te-cli/te-cli.md | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index b5e961c8b..4ead71cff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /metadata/languages.json - ############### # folder # ############### @@ -31,6 +30,7 @@ target/ .vscode/ .vs/ +.claude/ ############### # temp file # diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 093d388c3..37af0a208 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -80,6 +80,15 @@ During Limited Public Preview, the CLI does not require a license; you only need +## Feedback and community + +During the preview, bug reports, feature requests, and general discussion happen in the public [TabularEditor/CLI](https://github.com/TabularEditor/CLI) repository on GitHub: + +- **Issues** — report bugs, request features, and track known problems. +- **Discussions** — ask questions, share feedback, and swap usage tips with other early adopters. + +The repository does not host the CLI source code; it exists to give the community a public place to reach us during the preview. + ## Next steps - @te-cli-install — download, install, verify. @@ -92,4 +101,3 @@ During Limited Public Preview, the CLI does not require a license; you only need - @te-cli-migrate — migrating from the Tabular Editor 2 command line. - From e32234f0ad7f85fbdf23a725c9226812b25e5887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20L=C3=B8nskov?= Date: Thu, 23 Apr 2026 12:24:46 +0200 Subject: [PATCH 4/9] Include file for preview notice --- content/features/te-cli/includes/te-cli-preview-notice.md | 2 ++ content/features/te-cli/te-cli-auth.md | 3 +-- content/features/te-cli/te-cli-automation.md | 3 +-- content/features/te-cli/te-cli-cicd.md | 3 +-- content/features/te-cli/te-cli-commands.md | 3 +-- content/features/te-cli/te-cli-config.md | 3 +-- content/features/te-cli/te-cli-install.md | 3 +-- content/features/te-cli/te-cli-interactive.md | 3 +-- content/features/te-cli/te-cli-migrate.md | 3 +-- content/features/te-cli/te-cli.md | 3 +-- 10 files changed, 11 insertions(+), 18 deletions(-) create mode 100644 content/features/te-cli/includes/te-cli-preview-notice.md diff --git a/content/features/te-cli/includes/te-cli-preview-notice.md b/content/features/te-cli/includes/te-cli-preview-notice.md new file mode 100644 index 000000000..fe5317ce4 --- /dev/null +++ b/content/features/te-cli/includes/te-cli-preview-notice.md @@ -0,0 +1,2 @@ +> [!IMPORTANT] +> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. Please refer to our [license agreement](TBD: ADD LINK TO EULA) diff --git a/content/features/te-cli/te-cli-auth.md b/content/features/te-cli/te-cli-auth.md index c8b0280ad..7aebf18ac 100644 --- a/content/features/te-cli/te-cli-auth.md +++ b/content/features/te-cli/te-cli-auth.md @@ -14,8 +14,7 @@ applies_to: --- # Authentication and Connections -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] The Tabular Editor CLI authenticates to Power BI Service, Microsoft Fabric, and Azure Analysis Services using the same Power BI Desktop client ID that Tabular Editor 3 uses. Tokens are cached locally so you authenticate once and re-run commands silently until the refresh token expires (typically 90 days). diff --git a/content/features/te-cli/te-cli-automation.md b/content/features/te-cli/te-cli-automation.md index 0ec3d70df..ba3ba7be6 100644 --- a/content/features/te-cli/te-cli-automation.md +++ b/content/features/te-cli/te-cli-automation.md @@ -14,8 +14,7 @@ applies_to: --- # Automation and Scripting -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] The Tabular Editor CLI is designed as a composable building block. Every command supports structured output, disables interactive prompts on demand, and returns predictable exit codes. The same primitives work equally well for shell pipelines, Python scripts, PowerShell automation, and agent-driven workflows. diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md index a193c2d14..0d9c9099a 100644 --- a/content/features/te-cli/te-cli-cicd.md +++ b/content/features/te-cli/te-cli-cicd.md @@ -14,8 +14,7 @@ applies_to: --- # CI/CD Integration -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] The Tabular Editor CLI is designed for unattended execution in continuous integration and delivery pipelines. A single binary, structured output, non-interactive mode, native CI annotations for GitHub Actions and Azure DevOps, and VSTEST-compatible test results make it a natural replacement for ad-hoc TE2 invocations. diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index edf57322f..75fd302cd 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -14,8 +14,7 @@ applies_to: --- # Command Reference -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] This page gives a short description and one example per command. Every command accepts `--help` for exhaustive flag documentation: diff --git a/content/features/te-cli/te-cli-config.md b/content/features/te-cli/te-cli-config.md index d7468cc7e..b03394f06 100644 --- a/content/features/te-cli/te-cli-config.md +++ b/content/features/te-cli/te-cli-config.md @@ -14,8 +14,7 @@ applies_to: --- # Configuration -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] The Tabular Editor CLI reads optional configuration from a JSON file. Configuration controls three things: where the CLI looks for Tabular Editor 3's shared data files (Preferences, macros, BPA rules), behavioral defaults (BPA gates, auto-format, validation), and the list of saved connection profiles. diff --git a/content/features/te-cli/te-cli-install.md b/content/features/te-cli/te-cli-install.md index 96e78ced6..b906b2848 100644 --- a/content/features/te-cli/te-cli-install.md +++ b/content/features/te-cli/te-cli-install.md @@ -14,8 +14,7 @@ applies_to: --- # Installation and Setup -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] The Tabular Editor CLI ships as a single self-contained executable named `te` (`te.exe` on Windows). It has no external runtime dependencies. diff --git a/content/features/te-cli/te-cli-interactive.md b/content/features/te-cli/te-cli-interactive.md index 061673130..a870e1ad5 100644 --- a/content/features/te-cli/te-cli-interactive.md +++ b/content/features/te-cli/te-cli-interactive.md @@ -14,8 +14,7 @@ applies_to: --- # Interactive Mode -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] Interactive mode is a guided REPL (read-eval-print loop) for exploring a model from the terminal. It's the gentlest on-ramp for users who are new to command lines, and a convenient workspace for ad-hoc sessions against a single model. diff --git a/content/features/te-cli/te-cli-migrate.md b/content/features/te-cli/te-cli-migrate.md index 288fba42d..870f0d2d3 100644 --- a/content/features/te-cli/te-cli-migrate.md +++ b/content/features/te-cli/te-cli-migrate.md @@ -14,8 +14,7 @@ applies_to: --- # Migrating from the TE2 Command Line -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] Teams with existing build pipelines that invoke `TabularEditor.exe` with TE2-style flags (`-S`, `-A`, `-D`, `-O`, `-C`, etc.) can adopt the new CLI incrementally. The Tabular Editor CLI accepts both command shapes: the new subcommand-based form (`te deploy`, `te bpa run`, …) and the legacy TE2 flag syntax, via a built-in compatibility layer. diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 37af0a208..e4b6e9c59 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -18,8 +18,7 @@ The Tabular Editor CLI (`te`) is a cross-platform command-line interface for Pow Use it to inspect, edit, validate, deploy, refresh, and test semantic models from a terminal — against local TMDL or BIM files, Power BI Desktop, or semantic models in Fabric and Power BI Service workspaces. -> [!IMPORTANT] -> The Tabular Editor CLI is in **Limited Public Preview**. It is offered for evaluation with a Tabular Editor account; no license is required during preview. Commands, flags, and outputs may change before general availability. **The preview build stops functioning after 2026-09-30.** We recommend against using the CLI in production CI/CD pipelines during preview. +[!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] ## Built for three audiences From bcd0add8a67b94e478b5df8aeec8639661c72396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20L=C3=B8nskov?= Date: Thu, 23 Apr 2026 14:32:47 +0200 Subject: [PATCH 5/9] Updates based on Jeroen's comments --- content/features/te-cli/te-cli.md | 22 +++++++++++----------- content/features/toc.md | 19 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index e4b6e9c59..7f3cc1f5c 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -14,7 +14,7 @@ applies_to: --- # Tabular Editor CLI (Limited Public Preview) -The Tabular Editor CLI (`te`) is a cross-platform command-line interface for Power BI and Analysis Services semantic models. It runs on Windows, macOS, and Linux as a single self-contained executable and wraps the same model engine (TOMWrapper) that powers Tabular Editor 3 Desktop. +The Tabular Editor CLI (`te`) is a cross-platform command-line interface for Power BI and Analysis Services semantic models. It runs on Windows, macOS, and Linux as a single self-contained executable and wraps the same model engine (TOMWrapper) that powers Tabular Editor 3. Use it to inspect, edit, validate, deploy, refresh, and test semantic models from a terminal — against local TMDL or BIM files, Power BI Desktop, or semantic models in Fabric and Power BI Service workspaces. @@ -36,16 +36,16 @@ The CLI organizes more than 50 commands into 10 families. Each family maps to a | Family | What it does | Example commands | | -- | -- | -- | -| Model I/O | Load, save, export, initialize models | `te load`, `te save`, `te export` | -| Model Editing | Get/set properties, add/remove/move objects | `te set`, `te add`, `te rm`, `te mv` | -| Inspection | List objects, search, diff, dependency analysis | `te ls`, `te find`, `te diff`, `te deps` | -| Analysis & Quality | Validate, run BPA, format DAX, analyze storage | `te validate`, `te bpa run`, `te format`, `te vertipaq` | -| Execution | Run DAX queries, C# scripts, macros | `te query`, `te script`, `te macro` | -| Deployment & Refresh | Deploy to workspace, trigger refresh, incremental refresh | `te deploy`, `te refresh`, `te incremental-refresh` | -| Testing | Assertion tests, snapshots, A/B comparison | `te test run` | -| Connection & Auth | Connect to workspaces, manage authentication and profiles | `te connect`, `te auth`, `te profile` | -| Configuration | Settings and licensing | `te config`, `te license` | -| Shell | Interactive mode, shell completions | `te interactive`, `te completion` | +| [Model I/O](xref:te-cli-commands#model-io) | Load, save, export, initialize models | [`te load`](xref:te-cli-commands#load), [`te save`](xref:te-cli-commands#save), [`te export`](xref:te-cli-commands#export) | +| [Model Editing](xref:te-cli-commands#model-editing) | Get/set properties, add/remove/move objects | [`te set`](xref:te-cli-commands#set), [`te add`](xref:te-cli-commands#add), [`te rm`](xref:te-cli-commands#rm), [`te mv`](xref:te-cli-commands#mv) | +| [Inspection](xref:te-cli-commands#inspection) | List objects, search, diff, dependency analysis | [`te ls`](xref:te-cli-commands#ls), [`te find`](xref:te-cli-commands#find), [`te diff`](xref:te-cli-commands#diff), [`te deps`](xref:te-cli-commands#deps) | +| [Analysis & Quality](xref:te-cli-commands#analysis-and-quality) | Validate, run BPA, format DAX, analyze storage | [`te validate`](xref:te-cli-commands#validate), [`te bpa run`](xref:te-cli-commands#bpa-run), [`te format`](xref:te-cli-commands#format), [`te vertipaq`](xref:te-cli-commands#vertipaq) | +| [Execution](xref:te-cli-commands#execution) | Run DAX queries, C# scripts, macros | [`te query`](xref:te-cli-commands#query), [`te script`](xref:te-cli-commands#script), [`te macro`](xref:te-cli-commands#macro) | +| [Deployment & Refresh](xref:te-cli-commands#deployment-and-refresh) | Deploy to workspace, trigger refresh, incremental refresh | [`te deploy`](xref:te-cli-commands#deploy), [`te refresh`](xref:te-cli-commands#refresh), [`te incremental-refresh`](xref:te-cli-commands#incremental-refresh) | +| [Testing](xref:te-cli-commands#testing) | Assertion tests, snapshots, A/B comparison | [`te test run`](xref:te-cli-commands#test-run) | +| [Connection & Auth](xref:te-cli-commands#connection-and-auth) | Connect to workspaces, manage authentication and profiles | [`te connect`](xref:te-cli-commands#connect), [`te auth`](xref:te-cli-commands#auth-login--status--logout), [`te profile`](xref:te-cli-commands#profile-list--show--set--remove) | +| [Configuration](xref:te-cli-commands#configuration) | Settings and licensing | [`te config`](xref:te-cli-commands#config-show--paths--init--set), [`te license`](xref:te-cli-commands#license) | +| [Shell](xref:te-cli-commands#shell) | Interactive mode, shell completions | [`te interactive`](xref:te-cli-commands#interactive), [`te completion`](xref:te-cli-commands#completion) | See @te-cli-commands for a full command reference with syntax, options, and examples for each command. diff --git a/content/features/toc.md b/content/features/toc.md index e46f3b476..3678df3f9 100644 --- a/content/features/toc.md +++ b/content/features/toc.md @@ -63,15 +63,16 @@ # Command Line and Integration ## @command-line-options -## [Tabular Editor CLI (Limited PuPr)](xref:te-cli) -### @te-cli-install -### @te-cli-auth -### @te-cli-commands -### @te-cli-config -### @te-cli-interactive -### @te-cli-automation -### @te-cli-cicd -### @te-cli-migrate +## Tabular Editor CLI (Limited PuPr) +### [Overview](xref:te-cli) +### [Installation and Setup](xref:te-cli-install) +### [Authentication and Connections](xref:te-cli-auth) +### [Command Reference](xref:te-cli-commands) +### [Custom Configuration](xref:te-cli-config) +### [Interactive Mode](xref:te-cli-interactive) +### [Automation and Scripting](xref:te-cli-automation) +### [CI/CD Integration](xref:te-cli-cicd) +### [Migrating from TE2 CLI](xref:te-cli-migrate) # Semantic Bridge for cross-platform translations ## @semantic-bridge From c097f53df63fb80f619703233ad5d74072d6e1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20L=C3=B8nskov?= Date: Thu, 23 Apr 2026 20:25:35 +0200 Subject: [PATCH 6/9] Update config titel --- content/features/te-cli/te-cli-config.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/features/te-cli/te-cli-config.md b/content/features/te-cli/te-cli-config.md index b03394f06..9ad32cf78 100644 --- a/content/features/te-cli/te-cli-config.md +++ b/content/features/te-cli/te-cli-config.md @@ -1,6 +1,6 @@ --- uid: te-cli-config -title: Configuration +title: Custom Configuration author: Peer Grønnerup updated: 2026-04-20 applies_to: @@ -12,7 +12,7 @@ applies_to: - product: Tabular Editor CLI full: true --- -# Configuration +# Custom Configuration [!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] From 4f26bbeabcdfe2d822e2dc61d71e09ae0e84a9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Gr=C3=B8nnerup?= Date: Wed, 6 May 2026 15:24:42 +0200 Subject: [PATCH 7/9] Update docs for CLI to comply with latest changes in commands, flags, auth etc. --- content/features/te-cli/te-cli-auth.md | 43 +++++++--- content/features/te-cli/te-cli-automation.md | 7 +- content/features/te-cli/te-cli-cicd.md | 4 +- content/features/te-cli/te-cli-commands.md | 85 ++++++++++++++------ content/features/te-cli/te-cli-install.md | 8 +- content/features/te-cli/te-cli-migrate.md | 4 +- content/features/te-cli/te-cli.md | 4 +- 7 files changed, 102 insertions(+), 53 deletions(-) diff --git a/content/features/te-cli/te-cli-auth.md b/content/features/te-cli/te-cli-auth.md index 7aebf18ac..894a05260 100644 --- a/content/features/te-cli/te-cli-auth.md +++ b/content/features/te-cli/te-cli-auth.md @@ -2,7 +2,7 @@ uid: te-cli-auth title: Authentication and Connections author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -25,14 +25,15 @@ The CLI supports the full Azure Identity credential chain: | Method | When to use | `--auth` value | | -- | -- | -- | | Interactive browser | Local development — opens the system browser | `interactive` (default) | -| Device code | SSH sessions, headless VMs, devcontainers | `device-code` | -| Service principal (client secret) | Automation, CI/CD | `env` or pass `-u / -p / -t` | -| Service principal (certificate) | Automation with certificate-based auth | Pass `--certificate` | +| Service principal (client secret) | Automation, CI/CD, headless / SSH / WSL | `spn` (with `-u / -p / -t`) or `env` | +| Service principal (certificate) | Automation with certificate-based auth | `spn` (with `-u / -t / --certificate`) | | Environment variables | `AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID` | `env` | | Managed identity | Azure VMs, Azure Container Apps, Azure Functions | `managed-identity` | The default (`auto`) tries environment credentials first, then falls back to interactive browser. +For headless, SSH, WSL, or devcontainer scenarios, use a service principal — `te auth login -u -p -t ` (or `--certificate`). The login is cached, so subsequent commands acquire tokens silently with `--auth auto`. + ## `te auth login` Authenticate and cache the result for subsequent commands: @@ -41,9 +42,6 @@ Authenticate and cache the result for subsequent commands: # Browser-based interactive login (default) te auth login -# Device code flow (headless / SSH / CI) -te auth login --device-code - # Service principal with client secret te auth login -u -p -t @@ -57,6 +55,8 @@ te auth login -u -t --certificate ./sp.pfx --certificate-passw te auth login --identity ``` +After a successful service-principal login the CLI **caches the SP record** so every subsequent `te` command can acquire tokens silently — no need to re-pass `-u / -p / -t` or set the `AZURE_CLIENT_*` environment variables. Pass `--save=false` for a one-shot login that doesn't update the cache, or run `te auth logout` to clear it. + > [!WARNING] > Passing secrets directly on the command line is visible in `ps` output and shell history. Prefer the `AZURE_CLIENT_SECRET` environment variable, or pipe the secret via stdin with `-p -`. @@ -81,15 +81,15 @@ te auth logout ## Credential storage -Tokens are cached under your home directory. File permissions are restricted to the current user (`0600` on POSIX): +Tokens and service-principal records are cached under your home directory. File permissions are restricted to the current user (`0600` on POSIX): | Platform | Location | Notes | | -- | -- | -- | -| Windows | `%USERPROFILE%\.te-cli\auth-record.json` | Token cache encrypted via DPAPI through Azure.Identity | -| Linux | `~/.te-cli/auth-record.json` | Token cache via libsecret through Azure.Identity | -| macOS | `~/.te-cli/token-cache.bin` | File-based cache (bypasses Keychain to avoid repeated prompts) | +| Windows | `%USERPROFILE%\.te-cli\auth-record.json`, `auth-record-spn.json` | DPAPI-encrypted via Azure.Identity | +| Linux | `~/.te-cli/auth-record.json`, `auth-record-spn.json` | Token cache via libsecret through Azure.Identity; SP record file-mode `0600` | +| macOS | `~/.te-cli/token-cache.bin`, `auth-record-spn.json` | File-based cache (bypasses Keychain to avoid repeated prompts); SP record file-mode `0600` | -Device-code and interactive browser flows use separate record files so they can coexist. +Interactive browser and service-principal flows use separate record files so they can coexist. `te auth logout` clears all cached records. ## `te connect` — set the active connection @@ -99,7 +99,7 @@ Device-code and interactive browser flows use separate record files so they can # Remote workspace te connect my-workspace my-model -# Local TMDL folder or .bim file +# Local TMDL folder, .bim file, or .SemanticModel container te connect ./my-model # Connect to a running Power BI Desktop instance (Windows only) @@ -107,10 +107,27 @@ te connect --local # Show the active connection te connect + +# Clear the active connection (and any workspace mirror) +te connect --clear ``` Active-connection state is per-terminal-session: opening a new terminal starts fresh. +### Workspace mode (`-w` / `--workspace`) + +`te connect -w ` pairs a primary source with a secondary mirror so every subsequent `--save` writes to both. Use it to keep a local working copy of a remote model in sync, or to push local edits to a workspace as you save: + +```bash +# Mirror remote workspace ↔ local TMDL folder +te connect Finance "Revenue Model" -w ./revenue-model + +# Mirror local source ↔ remote workspace (initial deploy + auto-redeploy on save) +te connect ./revenue-model -w Finance "Revenue Model" +``` + +Save order is always **local first, then remote**, so the on-disk copy reflects the latest user change even if the server push fails. See @te-cli-commands#workspace-mode-w--workspace for `--workspace-format`, overwrite semantics, and clearing the mirror. + ## Connecting to different clouds The CLI detects the correct scope from the server URL for: diff --git a/content/features/te-cli/te-cli-automation.md b/content/features/te-cli/te-cli-automation.md index ba3ba7be6..ddd0374d3 100644 --- a/content/features/te-cli/te-cli-automation.md +++ b/content/features/te-cli/te-cli-automation.md @@ -2,7 +2,7 @@ uid: te-cli-automation title: Automation and Scripting author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -173,11 +173,12 @@ The resulting TMSL can be reviewed in a pull request, committed, executed by the ## Useful patterns -- **Idempotent removes.** `te rm Sales/OldMeasure --if-exists --save` exits `0` whether or not the object existed — safe to re-run. +- **Idempotent creates and removes.** `te add Sales/Marker -t Measure -i "0" --if-not-exists --save` and `te rm Sales/OldMeasure --if-exists --save` both exit `0` whether or not the object existed — safe to re-run in CI. - **Dry-run diffs.** `te replace` is dry-run by default; add `--save` only when you're satisfied with the preview. - **Emit TMSL for review.** `te deploy ./model --xmla deploy.tmsl` produces the deployment script without touching the server — useful for DBA review or manual apply. -- **Path-only output.** `te ls --paths-only` and `te find --paths-only` emit one object path per line, ideal for piping to `xargs`, `te get`, or `te set`. +- **Path-only output.** `te ls --paths-only` and `te find --paths-only` emit one object path per line, ideal for piping to `xargs`, `te get`, or `te set`. The model-level containers (`te ls Measures`, `te ls Columns`) compose well with this for whole-model sweeps. - **Benchmarking queries.** `te query --trace --cold --runs 5` runs a DAX query with cold cache, five iterations, and captures FE/SE trace events. +- **Step timings in CI logs.** Long-running commands (`te deploy`, `te refresh`, `te script`, `te validate`) include a `durationMs` field in JSON output — useful for surfacing per-step timings in pipeline summaries. ## Related pages diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md index 0d9c9099a..0b4706072 100644 --- a/content/features/te-cli/te-cli-cicd.md +++ b/content/features/te-cli/te-cli-cicd.md @@ -2,7 +2,7 @@ uid: te-cli-cicd title: CI/CD Integration author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -205,7 +205,7 @@ Commit these artifacts to git, upload them to the pipeline's artifact storage, o | Approach | When to use | Notes | | -- | -- | -- | | Service principal via env vars (`AZURE_CLIENT_ID` / `AZURE_CLIENT_SECRET` / `AZURE_TENANT_ID`, `--auth env`) | General CI/CD | Map pipeline secrets to environment variables at the step or job level. Never pass secrets in command arguments. | -| Service principal via flags (`te auth login -u ... -p -`, reading secret from stdin) | One-off automation | Pipe the secret rather than interpolating it: `echo $SECRET | te auth login -u $ID -p - -t $TENANT`. | +| Service principal via `te auth login` once per job (`echo $SECRET \| te auth login -u $ID -p - -t $TENANT`) | Multi-step jobs | The login is cached, so subsequent `te` commands acquire tokens silently — no need to set `AZURE_CLIENT_*` for every step or re-pass `-u/-p/-t`. Pipe the secret via stdin rather than interpolating it. | | Managed identity (`--auth managed-identity`) | Azure VMs, Container Apps, Azure Functions | No secrets to manage. Preferred in Azure-hosted environments. | | Certificate (`--certificate `) | Enterprise scenarios with cert rotation | Mount the certificate as a secure file step; pass `--certificate-password` via env. | diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index 75fd302cd..6c9c46d53 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -2,7 +2,7 @@ uid: te-cli-commands title: Command Reference author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -47,7 +47,7 @@ These flags are available on every command and sit before or after the subcomman | `-s, --server ` | Workspace name or endpoint (e.g., `MyWorkspace`, `powerbi://...`, `asazure://...`, `localhost`). | | `-d, --database ` | Semantic model name on the workspace. | | `--local` | Connect to a locally running Power BI Desktop instance (Windows only). | -| `--auth ` | Auth method: `auto`, `interactive`, `device-code`, `env`, `managed-identity` (default: `auto`). | +| `--auth ` | Auth method: `auto`, `interactive`, `spn`, `env`, `managed-identity` (default: `auto`). | | `--output ` | Output format: `auto`, `text`, `json`, `csv` (default: `auto` — text for TTY, JSON for pipes). | | `--recent [N]` | Use a recently used model. No value = interactive picker; `N` = Nth most recent (1 = last used). | | `--non-interactive` | Disable all interactive prompts. Fail with an actionable error if required input is missing. | @@ -69,27 +69,24 @@ te load -s MyWorkspace -d MyModel # Remote workspace ### save -Save a model to disk in a specified format. +Save a model to disk. Use it to write a remote workspace model to local files, convert formats, or persist edits back to the source. -- `-o, --output-path ` — target file or folder (required). -- `--format ` — `tmdl` (default), `bim`, `te-folder`, `pbip`, `database.json`. -- `--force` — skip validation and overwrite existing output. +- `-o, --output-path ` — target file or folder. **Optional** — when omitted, `te save` writes back to the source location, preserving the original format. +- `--format ` — `tmdl`, `bim`, `te-folder`, `pbip`, `database.json`. Defaults to inferring from the loaded model (BIM source → BIM, TMDL `SemanticModel/` → TMDL under `definition/`). +- `--force` — skip validation and overwrite existing output. Some refusals (ambiguous containers, multi-`SemanticModel` project roots) fire even under `--force`. - `--skip-bpa` / `--fix-bpa` — bypass or auto-fix the BPA gate. +- `--skip-validation` — skip DAX semantic analysis and validation for fast passthrough downloads. - `--supporting-files` — generate Fabric supporting files (`.platform`, `definition.pbism`). ```bash +te save # Save back to source (no -o needed) te save ./model.bim -o ./tmdl-out # Convert BIM to TMDL te save -o ./project --format pbip # Save as a PBIP project +te save -o ./out -s my-workspace -d my-model --skip-validation # Fast download ``` -### export - -Export a model from a workspace to local disk. - -```bash -te export -o ./out -s my-workspace -d my-model -te export -o ./model.bim --format bim -``` +> [!TIP] +> Use `te save -o -s -d ` to download a remote model to disk. Pair with `--skip-validation` for the fastest passthrough when you only need the bytes (no DAX semantic analysis). ### open @@ -124,13 +121,16 @@ te set Sales -q isHidden -i true --save ### add -Add an object to the model. The type is inferred from the `.Type` suffix on the path: -`.Measure`, `.Table`, `.CalculatedColumn`, `.Role`, plus relationship shorthand -`"Sales[Key]->Dim[Key]"`. +Add an object to the model. Pass the object path and the type via `-t` / `--type`. Relationships keep their shorthand syntax (`Sales[Key]->Dim[Key]`). + +- `-t, --type ` — object type. Common values: `Table`, `Measure`, `Column`, `CalculatedColumn`, `Hierarchy`, `Role`, `Perspective`, `Culture`, `CalculationGroup`, `CalculationItem`. Tab-completion is supported; full list in `te add --help`. +- `--if-not-exists` — exit `0` without error if the object already exists. Use this for idempotent CI/CD pipelines. ```bash -te add Sales/Revenue.Measure -i "SUM(Sales[Amount])" --save -te add "Sales[ProdKey]->Product[ProdKey]" --save +te add Sales/Revenue -t Measure -i "SUM(Sales[Amount])" --save +te add Sales -t Table --save +te add "Sales[ProdKey]->Product[ProdKey]" --save # Relationship shorthand +te add Sales/MarketingFlag -t CalculatedColumn -i "..." --if-not-exists --save ``` For data-bound tables, `te add` also supports schema detection from SQL, Lakehouse, or Warehouse sources. See `te add --help` for `--source`, `--endpoint`, `--source-table`, `--columns`, etc. @@ -170,14 +170,15 @@ te replace "SUM" "SUMX" --regex --in expressions --save ### ls -List objects with filesystem-like navigation. +List objects with filesystem-like navigation. Both model-level containers (`Tables`, `Measures`, `Columns`, `Hierarchies`, `Relationships`, `Roles`, `Perspectives`, `Cultures`) and table-scoped containers (`Sales/Measures`, `Sales/Columns`, …) are supported. ```bash te ls # Tables (active model) te ls Sales # Columns and measures in Sales -te ls Sales/Measures # Only measures -te ls --type measure # All measures across tables -te ls --paths-only # One path per line, suitable for piping +te ls Sales/Measures # Measures in Sales +te ls Measures # All measures across the model +te ls Columns --paths-only # One Table/Column per line, suitable for piping +te ls --type measure # Same as `te ls Measures` ``` ### get @@ -214,10 +215,15 @@ te diff old.bim new.bim ### deps -Analyze an object's upstream and downstream dependencies. +Analyze an object's upstream and downstream dependencies, or surface unused objects across the model. + +- `--unused` — list measures, calculated columns, and **all data columns** that no DAX references and that aren't used in any relationship, hierarchy level, sort-by, variation, AlternateOf base, or calendar time role. Each result shows `(hidden)` in text mode and an `isHidden` field in JSON. +- `--hidden` — narrow `--unused` to hidden objects only. Hidden, unused objects are the safest prune candidates because nothing user-facing depends on them. ```bash -te deps "Sales/Revenue" +te deps "Sales/Revenue" # Upstream + downstream for one object +te deps --unused # All unused measures and columns +te deps --unused --hidden # Only hidden, unused objects ``` ## Analysis and quality @@ -338,6 +344,18 @@ te macro rm # Remove a macro te macro sort # Sort and re-assign IDs ``` +`te macro run` accepts: + +- `--on ` — set the macro's selection context to one or more model objects (comma-separated paths). Equivalent to right-clicking objects in TE3 and invoking the macro from the context menu. +- `--save` / `--save-to` — persist any changes the macro makes. + +Macros that emit tables via `dataTable.Output()` render formatted output in the terminal, so DAX-style query macros work the same in `te macro run` as they do in TE3. + +```bash +te macro run "Hide all measures" +te macro run "Format DAX" --on "Sales/Revenue,Sales/Margin" --save +``` + ## Deployment and refresh ### deploy @@ -427,6 +445,23 @@ te connect my-workspace my-model # Remote te connect ./model # Local te connect --local # Power BI Desktop (Windows) te connect --profile prod # Activate a saved profile +te connect --clear # Clear the active connection (and any workspace mirror) +``` + +#### Workspace mode (`-w` / `--workspace`) + +Pair a primary source with a secondary target so every subsequent `--save` mirrors the model between the two. Useful for keeping a local working copy of a remote workspace, or pushing local edits to a workspace as you save. + +- `te connect -w ./src` — primary is remote; `./src` receives an initial TMDL export and mirrors every save. +- `te connect ./src -w ` — primary is local; an initial deploy pushes the model to the workspace, and subsequent saves re-deploy automatically. +- `--workspace-format ` — choose the on-disk format when mirroring to a folder/file (e.g., `-w ./model.bim` infers BIM). +- `--force` — required when the target already exists (non-empty folder, existing database). Without it, `te connect` shows an interactive `y/n` prompt with `n` as the safe default. + +Once active, `te set --save`, `te rm --save`, `te script --save`, etc. all dual-save transparently. Save order is always **local first, then remote** so the on-disk copy reflects the latest user change even if the server push fails. Clear the mirror with `te connect --clear`. + +```bash +te connect Finance "Revenue Model" -w ./revenue-model # Mirror remote → local TMDL +te connect ./revenue-model -w Finance "Revenue Model" # Mirror local → remote ``` ### auth login / status / logout diff --git a/content/features/te-cli/te-cli-install.md b/content/features/te-cli/te-cli-install.md index b906b2848..2cc5aa6e1 100644 --- a/content/features/te-cli/te-cli-install.md +++ b/content/features/te-cli/te-cli-install.md @@ -2,7 +2,7 @@ uid: te-cli-install title: Installation and Setup author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -68,11 +68,7 @@ chmod +x ~/.local/bin/te echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # or ~/.bashrc ``` -On macOS, the first run may trigger a Gatekeeper quarantine warning. Remove the quarantine attribute with: - -```bash -xattr -d com.apple.quarantine ~/.local/bin/te -``` +On macOS, the binary is signed with our Apple Developer ID and notarized by Apple, so the first run completes without a "cannot verify developer" Gatekeeper warning. Network access on first run is recommended so Gatekeeper can fetch the notarization ticket; offline first-runs may briefly prompt before being unblocked once network returns. ## Verify diff --git a/content/features/te-cli/te-cli-migrate.md b/content/features/te-cli/te-cli-migrate.md index 870f0d2d3..1dee24142 100644 --- a/content/features/te-cli/te-cli-migrate.md +++ b/content/features/te-cli/te-cli-migrate.md @@ -2,7 +2,7 @@ uid: te-cli-migrate title: Migrating from the TE2 Command Line author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -81,7 +81,7 @@ A non-exhaustive summary of the most commonly used flags. Run `te migrate` for t | `-W` / `-WARN` | (default) | Warnings always reported in deploy results. | | `-E` / `-ERR` | (default) | Deploy returns non-zero exit on DAX errors. | | `-SC` / `-SCHEMACHECK` | *Not yet implemented.* | TE2 schema check connects to actual data sources. Different from `te validate` (DAX semantic validation, no data source connection). | -| `-L` / `-LOGIN ` (after `-D`) | *Not yet implemented.* | Use `te auth login` with service principal or env-based credentials instead — see @te-cli-auth. | +| `-L` / `-LOGIN ` (after `-D`) | `te auth login -u -p -t ` | Use service principal or env-based credentials. The login is cached, so subsequent commands acquire tokens silently — see @te-cli-auth. | ## Migration playbook diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 7f3cc1f5c..157c4c256 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -2,7 +2,7 @@ uid: te-cli title: Tabular Editor CLI (Limited Public Preview) author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-06 applies_to: products: - product: Tabular Editor 2 @@ -36,7 +36,7 @@ The CLI organizes more than 50 commands into 10 families. Each family maps to a | Family | What it does | Example commands | | -- | -- | -- | -| [Model I/O](xref:te-cli-commands#model-io) | Load, save, export, initialize models | [`te load`](xref:te-cli-commands#load), [`te save`](xref:te-cli-commands#save), [`te export`](xref:te-cli-commands#export) | +| [Model I/O](xref:te-cli-commands#model-io) | Load, save, convert, initialize models | [`te load`](xref:te-cli-commands#load), [`te save`](xref:te-cli-commands#save), [`te init`](xref:te-cli-commands#init) | | [Model Editing](xref:te-cli-commands#model-editing) | Get/set properties, add/remove/move objects | [`te set`](xref:te-cli-commands#set), [`te add`](xref:te-cli-commands#add), [`te rm`](xref:te-cli-commands#rm), [`te mv`](xref:te-cli-commands#mv) | | [Inspection](xref:te-cli-commands#inspection) | List objects, search, diff, dependency analysis | [`te ls`](xref:te-cli-commands#ls), [`te find`](xref:te-cli-commands#find), [`te diff`](xref:te-cli-commands#diff), [`te deps`](xref:te-cli-commands#deps) | | [Analysis & Quality](xref:te-cli-commands#analysis-and-quality) | Validate, run BPA, format DAX, analyze storage | [`te validate`](xref:te-cli-commands#validate), [`te bpa run`](xref:te-cli-commands#bpa-run), [`te format`](xref:te-cli-commands#format), [`te vertipaq`](xref:te-cli-commands#vertipaq) | From 63a9386d60b83ae744d0f9e75a9e748457c176df Mon Sep 17 00:00:00 2001 From: Daniel Otykier Date: Tue, 12 May 2026 22:34:03 +0200 Subject: [PATCH 8/9] cli docs refinement (#318) --- content/features/te-cli/te-cli-commands.md | 191 ++++++++++++++---- content/features/te-cli/te-cli-interactive.md | 17 +- content/features/te-cli/te-cli.md | 4 +- 3 files changed, 175 insertions(+), 37 deletions(-) diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index 6c9c46d53..91bda6dd4 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -2,7 +2,7 @@ uid: te-cli-commands title: Command Reference author: Peer Grønnerup -updated: 2026-05-06 +updated: 2026-05-12 applies_to: products: - product: Tabular Editor 2 @@ -26,16 +26,95 @@ te --help > [!NOTE] > During preview, the CLI's `--help` output is the authoritative reference for flags and options. The content on this page is hand-curated and will lag `--help` for anything added between preview releases. -## Object path syntax +## Object paths -Most commands accept object paths of the form: +Object addressing in the CLI uses a single grammar that's shared across every command. Two flavours of path appear in the reference below: -- `Sales` — a table. -- `Sales/Revenue` — a measure or column. -- `Sales/Measures` — a sub-container inside a table (`Measures`, `Columns`, `Partitions`, `Hierarchies`). -- `Relationships`, `Roles`, `Perspectives`, `Cultures` — model-level containers. +- **``** — resolves to **exactly one** object or container. Used by commands that operate on a single target: `te get`, `te set`, `te add`, `te rm`, `te mv`, `te format -p`, `te deps`, `te macro run --on`. +- **``** — resolves to **zero or more** objects, with wildcard support. Used by commands that operate on a set: `te ls`, `te bpa run --path`, and other inspection-style commands. -Paths are consistent across `te get`, `te set`, `te add`, `te rm`, `te mv`, `te find`, `te replace`, and `te ls`. +The two share the same lexer; the only differences are that filter paths permit `*` wildcards while object paths do not, and object paths permit DAX bracket-suffix while filter paths do not. + +### Segments and separators + +A path is a slash-separated sequence of **segments**. Each segment names a single step — a table, a child object, or a container keyword. + +``` +Sales # one segment +Sales/Revenue # two segments +Roles/Admin/Members/bob # four segments +``` + +Empty input and `.` both mean "the model root" — the implicit starting point for filter paths and the explicit subject for `te get .`-style queries. + +### Quoting + +Bare segments cover the common case. When a name contains spaces, slashes, brackets, or any character that would otherwise be parsed as syntax, **quote** the segment. The CLI follows DAX quoting conventions, so quoting in `te` paths matches what you'd type inside a DAX expression: + +| Form | Use for | Escape rule | +| -- | -- | -- | +| `'Net Sales'` | Tables, named objects with spaces. | Double the quote (`'Bob''s'` → `Bob's`). | +| `"Net Sales"` | Same as above; cross-shell convenience when single-quote escaping is awkward. | Double the quote (`"He said ""hi"""` → `He said "hi"`). | +| `[Sales Amount]` | DAX bracket-suffix on a table (`'Sales'[Sales Amount]`) or a lone-bracket model-wide reference (`[Total Sales]`). Object paths only. | Double the closing bracket (`[foo]]bar]` → `foo]bar`). | + +Wildcards inside quoted segments are literal. `'Sa*'` matches a table named exactly `Sa*` — quoting disables glob matching for that segment. + +### DAX-style references (object paths only) + +Two DAX-shaped forms are accepted anywhere a `` is allowed: + +- **`'Table'[Member]`** — equivalent to `Table/Member`. The bracket-suffix biases ambiguous matches toward columns and measures over hierarchies/partitions. +- **`[Member]`** — a *lone* bracket, with no preceding table. Searches the whole model for a measure or column with that name. Measures win when both exist. + +```bash +te get "'Sales'[Amount]" # Same as te get Sales/Amount +te get "'Net Sales'[Sales Amount]" # Spaced names via DAX form +te get "[Total Sales]" # Model-wide measure-or-column lookup +``` + +### Containers and keywords + +Several bare names act as **container keywords**. A keyword can stand alone (listing the whole container) or appear inside a path (jumping into that sub-collection on the current parent). + +| Keyword | Scope | Meaning | +| -- | -- | -- | +| `Tables`, `Measures`, `Columns`, `Hierarchies`, `Partitions` | Model | All objects of that kind across the model. | +| `Relationships`, `Roles`, `Perspectives`, `Cultures`, `DataSources`, `Expressions`, `CalculationGroups`, `Functions`, `Annotations` | Model | Model-level containers. | +| `Measures`, `Columns`, `Hierarchies`, `Partitions`, `Calendars`, `CalculationItems` | Table | Sub-containers under a table. | +| `Levels` | Hierarchy | Levels of a hierarchy. | +| `Members`, `TablePermissions` (alias `Permissions`) | Role | Children of a role. | + +A few examples make the difference between bare and container-scoped paths concrete: + +```bash +te get Sales/Revenue # Measure or column on Sales +te get Sales/Measures/Revenue # Same, container-scoped — disambiguates if other kinds share the name +te get Sales/Geography/Levels/Year # Specific level of a hierarchy +te get Roles/Admin/Members/bob@example.com # Role member +te get Sales/refreshPolicy # Refresh-policy sub-object on a table +te get "Measures/Revenue/KPI" # KPI sub-object of a measure +``` + +Quote a segment to force literal-name matching when a real object name happens to coincide with a keyword. The table literally named `Tables` is `'Tables'`, addressed by `te get "'Tables'"`. + +### Wildcards in filter paths + +Filter paths add a single wildcard character — `*` — that matches any run of characters within one segment (greedy, single-segment). Wildcards are how `te ls` and similar commands narrow their results. + +```bash +te ls Sa* # Tables whose name starts with Sa +te ls Sales/*Amount # Children of Sales whose name ends with Amount +te ls */Amount # An Amount column/measure across every table +te ls Roles/Re*/Members # Members of every role matching Re* +``` + +A filter path with **N segments** produces **N-level-deep** results — wildcards never auto-expand a level beyond what you typed. The single-segment shortcut `te ls Sales` is the exception: an unqualified, non-wildcarded table name expands to the table's direct children to match the "show me what's in Sales" intent. `te ls Sa*`, in contrast, returns just the matching tables — no expansion. + +DAX bracket-suffix is rejected in filter paths; quote names containing `[` and `]` if you need to match them literally. + +### Errors and hints + +Misspelled segments emit a contextual error with a "did you mean" hint when the CLI can guess what you meant. Missing-parent paths fail before the leaf check, so the message points at the segment that's actually wrong. Empty containers (e.g., `te ls Hierarchies` on a model with none) emit a dim "nothing here" hint rather than an error. ## Global options @@ -48,7 +127,7 @@ These flags are available on every command and sit before or after the subcomman | `-d, --database ` | Semantic model name on the workspace. | | `--local` | Connect to a locally running Power BI Desktop instance (Windows only). | | `--auth ` | Auth method: `auto`, `interactive`, `spn`, `env`, `managed-identity` (default: `auto`). | -| `--output ` | Output format: `auto`, `text`, `json`, `csv` (default: `auto` — text for TTY, JSON for pipes). | +| `--output ` | Output format: `auto`, `text`, `json`, `csv`, `tmsl` (alias `bim`), `tmdl` (default: `auto` — text for TTY, JSON for pipes). `tmsl`/`tmdl` are accepted by `te get` and `te ls` for whole-object serialization. | | `--recent [N]` | Use a recently used model. No value = interactive picker; `N` = Nth most recent (1 = last used). | | `--non-interactive` | Disable all interactive prompts. Fail with an actionable error if required input is missing. | | `--debug` | Enable debug logging to stderr (connection strings, auth flow, timing). | @@ -108,7 +187,7 @@ te init ./new-model ### set -Set a property on a model object. +Set a property on a model object. Accepts a ``. - `-q ` — property name (e.g., `expression`, `formatString`, `description`, `isHidden`). - `-i ` — value (use `-` to read from stdin). @@ -116,12 +195,13 @@ Set a property on a model object. ```bash te set Sales/Amount -q expression -i "SUM(Sales[Amt])" --save +te set "'Net Sales'[Sales Amount]" -q formatString -i "#,0" --save # DAX form with spaced names te set Sales -q isHidden -i true --save ``` ### add -Add an object to the model. Pass the object path and the type via `-t` / `--type`. Relationships keep their shorthand syntax (`Sales[Key]->Dim[Key]`). +Add an object to the model. Pass a `` for the new object (the parent must already exist; the trailing segment is the new name) and the type via `-t` / `--type`. Relationships keep their shorthand syntax (`Sales[Key]->Dim[Key]`). - `-t, --type ` — object type. Common values: `Table`, `Measure`, `Column`, `CalculatedColumn`, `Hierarchy`, `Role`, `Perspective`, `Culture`, `CalculationGroup`, `CalculationItem`. Tab-completion is supported; full list in `te add --help`. - `--if-not-exists` — exit `0` without error if the object already exists. Use this for idempotent CI/CD pipelines. @@ -131,23 +211,26 @@ te add Sales/Revenue -t Measure -i "SUM(Sales[Amount])" --save te add Sales -t Table --save te add "Sales[ProdKey]->Product[ProdKey]" --save # Relationship shorthand te add Sales/MarketingFlag -t CalculatedColumn -i "..." --if-not-exists --save +te add Perspectives/Default/Sales --save # Include Sales in the Default perspective +te add Roles/Reader -t Role --save # New role at the model level ``` For data-bound tables, `te add` also supports schema detection from SQL, Lakehouse, or Warehouse sources. See `te add --help` for `--source`, `--endpoint`, `--source-table`, `--columns`, etc. ### rm -Remove an object. Checks dependents by default; use `--force` to bypass, `--if-exists` for idempotent removes. +Remove an object. Accepts a ``. Checks dependents by default; use `--force` to bypass, `--if-exists` for idempotent removes. ```bash te rm Sales/Revenue --save +te rm "'Sales'[Revenue]" --save # DAX form te rm Sales/Revenue --dry-run # Preview only te rm Sales/OldMeasure --if-exists --save # Idempotent ``` ### mv -Move or rename a model object. +Move or rename a model object. Both source and destination are `` arguments. ```bash te mv Sales/Revenue Finance/Revenue --save # Move measure to another table @@ -161,6 +244,8 @@ Find and replace text across model objects. Dry-run by default; add `--save` to - `--in ` — `names`, `expressions`, `descriptions`, `displayFolders`, `formatStrings`, `annotations`, `all`. - `--regex`, `--case-sensitive`. +`--in expressions` walks every expression-bearing property: measure `Expression` and `DetailRowsExpression`, KPI `TargetExpression` / `StatusExpression` / `TrendExpression`, partition source and polling M, table-permission `FilterExpression`, calculation-group selection expressions, and calculated-column DAX. Adding new expression-shaped properties to the model surfaces them automatically. + ```bash te replace "OldTable" "NewTable" --in expressions --save te replace "SUM" "SUMX" --regex --in expressions --save @@ -170,25 +255,48 @@ te replace "SUM" "SUMX" --regex --in expressions --save ### ls -List objects with filesystem-like navigation. Both model-level containers (`Tables`, `Measures`, `Columns`, `Hierarchies`, `Relationships`, `Roles`, `Perspectives`, `Cultures`) and table-scoped containers (`Sales/Measures`, `Sales/Columns`, …) are supported. +List objects with filesystem-like navigation. Takes a `` argument supporting wildcards. Both model-level containers (`Tables`, `Measures`, `Columns`, `Hierarchies`, `Relationships`, `Roles`, `Perspectives`, `Cultures`) and table-scoped containers (`Sales/Measures`, `Sales/Columns`, …) are supported. + +- `--type ` — narrow to one object kind (`table`, `measure`, `column`, `hierarchy`, `partition`, `relationship`, `role`, `perspective`, `culture`). With no `` this is equivalent to typing the matching container keyword. +- `--paths-only` — emit one object path per line, suitable for piping to `xargs`, `te get`, or `te set`. +- `--no-multiline` — collapse multi-line cells (typically DAX or M expressions) to a single line and truncate, so rows stay scannable in wide tables. Text output only; JSON/CSV/TMSL output is unaffected. +- `--output tmsl` (alias `bim`) — emit the matching objects as a TMSL/BIM script. Useful for `te ls Tables --output bim > tables.json`. `--output tmdl` is not supported by `ls` (TMDL is single-object only — use `te get`). ```bash -te ls # Tables (active model) -te ls Sales # Columns and measures in Sales -te ls Sales/Measures # Measures in Sales -te ls Measures # All measures across the model -te ls Columns --paths-only # One Table/Column per line, suitable for piping -te ls --type measure # Same as `te ls Measures` +te ls # All tables in the model +te ls Sales # All children of Sales (columns + measures + hierarchies + partitions) +te ls Sales/Measures # Just Sales's measures +te ls Sales/*Amount # Children of Sales whose name ends with Amount +te ls Sa* # Tables whose name starts with Sa (no auto-expansion) +te ls */Amount # An Amount column/measure across every table +te ls Roles/Re*/Members # Members of every role matching Re* +te ls Sales/Geography/Levels # All levels of the Geography hierarchy +te ls "'Net Sales'/'Sales Amount'" # Quote names containing spaces +te ls Measures --paths-only # One Table/Measure per line for piping +te ls --type measure # Same as `te ls Measures` +te ls Measures --no-multiline # Wide table with column dividers, single-line DAX +te ls Tables --output bim > tables.json # All tables emitted as TMSL/BIM ``` ### get -Get properties of a model object. +Get properties of a model object. Takes a ``. - `-q, --query ` — fetch a single property (e.g. `expression`, `formatString`). +- `-t, --type ` — disambiguate when the path matches multiple table-children (e.g. a column and a hierarchy with the same name). Values: `Measure`, `Column`, `CalculatedColumn`, `Hierarchy`, `Calendar`, `Partition`, `CalculationItem`. +- `--output tmsl` (alias `bim`) — emit the resolved object as TMSL/BIM JSON. +- `--output tmdl` — emit the resolved object as TMDL (named objects only). + +`te get` and `te ls` share a single descriptor catalog, so every property surfaces the same way across formats — the text table, JSON, and CSV all see the same set, and adding a new property to the model exposes it everywhere. ```bash -te get Sales/Amount -q expression # Print DAX +te get Sales/Amount -q expression # Print DAX +te get "'Sales'[Amount]" # DAX form: same as Sales/Amount +te get "[Total Sales]" # Lone-bracket: model-wide measure-or-column +te get "'Net Sales'[Sales Amount]" -q expression # DAX form with spaced names +te get "Sales/Revenue/KPI" # KPI sub-object of a measure +te get Sales --output tmdl # Emit the table as TMDL +te get Sales --output bim # Emit the table as TMSL/BIM te get Model -q description ``` @@ -198,10 +306,14 @@ Search for text across model objects. - `--in ` — as per `te replace` (default `all`). - `--regex`, `--case-sensitive`, `--paths-only`. +- `--no-multiline` — collapse multi-line match context to a single line. Text output only. + +`--in expressions` covers every `IExpressionObject` in the model — including KPI `TargetExpression` / `StatusExpression` / `TrendExpression`, measure `DetailRowsExpression`, partition source/polling M, table-permission `FilterExpression`, and calculation-group `MultipleOrEmptySelection` / `NoSelection` expressions — so a literal like `123` set on a KPI's target turns up the same way a measure body would. ```bash te find "CALCULATE" --in expressions te find "Revenue" --in names +te find "CALCULATE" --in expressions --paths-only | xargs -I{} te get {} -q expression ``` ### diff @@ -215,13 +327,14 @@ te diff old.bim new.bim ### deps -Analyze an object's upstream and downstream dependencies, or surface unused objects across the model. +Analyze an object's upstream and downstream dependencies, or surface unused objects across the model. The single-object form takes a ``. - `--unused` — list measures, calculated columns, and **all data columns** that no DAX references and that aren't used in any relationship, hierarchy level, sort-by, variation, AlternateOf base, or calendar time role. Each result shows `(hidden)` in text mode and an `isHidden` field in JSON. - `--hidden` — narrow `--unused` to hidden objects only. Hidden, unused objects are the safest prune candidates because nothing user-facing depends on them. ```bash -te deps "Sales/Revenue" # Upstream + downstream for one object +te deps Sales/Revenue # Upstream + downstream for one object +te deps "'Sales'[Revenue]" # DAX form is accepted everywhere a is te deps --unused # All unused measures and columns te deps --unused --hidden # Only hidden, unused objects ``` @@ -248,12 +361,17 @@ Run Best Practice Analyzer rules against a model. - `--fix` — apply auto-fix expressions where rules define them. - `--fail-on ` — `error` (default) or `warning`. - `--ci ` / `--trx ` — CI annotations and TRX output. -- `--skip-bpa`, `--no-model-rules`, `--no-defaults`, `--rule `, `--path `, `--vpax `, `--vpa-rules`. +- `--path ` — limit analysis to the tables containing the matched objects. Accepts wildcards and container keywords; same grammar as `te ls`. +- `--no-multiline` — collapse multi-line cells in the violations table to a single line. Text output only. +- `--skip-bpa`, `--no-model-rules`, `--no-defaults`, `--rule `, `--vpax `, `--vpa-rules`. ```bash te bpa run --fail-on error --ci github te bpa run --fix --save te bpa run --rule PERF_UNUSED_HIDDEN_COLUMN +te bpa run --path Sales # Tables touched by the Sales filter only +te bpa run --path 'Sa*' # Wildcard — every table starting with Sa +te bpa run --path Sales/Measures # Path filter applied to the matched tables ``` ### bpa rules @@ -287,7 +405,7 @@ te vertipaq --import stats.vpax # Analyze offline Format DAX or M/Power Query expressions. - `-e, --expression ` — format a single inline expression. -- `-p, --path ` — format a specific measure/column. +- `-p, --path ` — format a specific measure/column. - `--lang ` — default `dax`. - `--save` / `--save-to` — persist formatted expressions. @@ -318,7 +436,7 @@ te query -f query.dax --output json ### script -Execute one or more C# scripts against a semantic model. +Execute one or more C# scripts against a semantic model. The CLI uses the same scripting host as Tabular Editor 3 Desktop, so a script that runs in TE3 runs unchanged here. - `-S, --script ` — `.cs` / `.csx` file (repeatable). - `-e, --expression ` — inline C# (use `-` for stdin). @@ -331,6 +449,12 @@ te script -e "Info(Model.Tables.Count)" echo "Info(Model.Name);" | te script -e - ``` +> [!IMPORTANT] +> Two behavioral details to know if you're porting an older script: +> +> - **No interactive selection in CLI scripts.** The TE3-Desktop helpers `SelectMeasure()`, `SelectTable()`, `SelectColumn()`, `SelectObject()`, and `SelectObjects()` throw `NotSupportedException` when called from `te script` — the CLI has no UI to pop up. Pre-resolve the object(s) outside the script and pass them in, or wrap the call in `try/catch` if the script is shared with TE3. +> - **Default `using` directives match TE3 Desktop.** Scripts that use `DataTable`, `File`, `StringBuilder`, or `Regex` must include the corresponding `using System.Data;` / `using System.IO;` / `using System.Text;` / `using System.Text.RegularExpressions;` directive explicitly. The previous wider CLI-only defaults are gone. + ### macro Manage and run Tabular Editor 3 macros from `MacroActions.json`. @@ -346,14 +470,15 @@ te macro sort # Sort and re-assign IDs `te macro run` accepts: -- `--on ` — set the macro's selection context to one or more model objects (comma-separated paths). Equivalent to right-clicking objects in TE3 and invoking the macro from the context menu. +- `--on ` — set the macro's selection context to a single named object (a table, measure, column, …). Equivalent to right-clicking that object in TE3 and invoking the macro from the context menu. - `--save` / `--save-to` — persist any changes the macro makes. Macros that emit tables via `dataTable.Output()` render formatted output in the terminal, so DAX-style query macros work the same in `te macro run` as they do in TE3. ```bash te macro run "Hide all measures" -te macro run "Format DAX" --on "Sales/Revenue,Sales/Margin" --save +te macro run "Format DAX" --on Sales/Revenue --save +te macro run "Format DAX" --on "'Net Sales'[Sales Amount]" --save # DAX form works in --on too ``` ## Deployment and refresh @@ -487,11 +612,7 @@ te config set autoFormat true ### license -Manage CLI license state. - -```bash -te license activate -``` +`te license` is reserved for the GA release and is not available in this preview build. The command is still wired up to the parser — so existing scripts that invoke it won't blow up at parse time — but every subcommand exits with status `1` and a "not available in this preview build" message. See the [Preview notice](xref:te-cli#preview-notice) on the overview page for the broader licensing outlook. ### migrate @@ -515,6 +636,8 @@ te interactive ./model # Start with a local model te interactive -s MyWorkspace -d MyModel # Start with a remote model ``` +Quoting and DAX-style references work the same as outside the session — see the [Object paths](#object-paths) section above and @te-cli-interactive for details on bracket-aware argv splitting inside the REPL. + ### completion Generate a shell completion script. See @te-cli-install. diff --git a/content/features/te-cli/te-cli-interactive.md b/content/features/te-cli/te-cli-interactive.md index a870e1ad5..0738d12bf 100644 --- a/content/features/te-cli/te-cli-interactive.md +++ b/content/features/te-cli/te-cli-interactive.md @@ -2,7 +2,7 @@ uid: te-cli-interactive title: Interactive Mode author: Peer Grønnerup -updated: 2026-04-20 +updated: 2026-05-12 applies_to: products: - product: Tabular Editor 2 @@ -51,6 +51,21 @@ Each command accepts `--help` the same way it does outside the session: te [MyModel]> deploy --help ``` +## Quoting and DAX-style paths + +The REPL line splitter recognises the same quoting forms as [object paths](xref:te-cli-commands#object-paths) so DAX-shaped references survive the trip through the parser as a single argument: + +- `'...'` and `"..."` — single- and double-quoted segments. The quote characters are stripped, doubled quotes escape a literal occurrence. +- `[...]` — bracketed segment. **Brackets are preserved** in the resulting argument so a path like `'Internet Sales'[Sales Amount]` reaches the command as one token that the path parser can re-interpret as a DAX reference. Doubled closing brackets (`]]`) stay verbatim for the same reason. + +``` +te [MyModel]> get 'Internet Sales'[Sales Amount] # One argument, DAX form +te [MyModel]> get [Total Sales] # Lone-bracket model-wide lookup +te [MyModel]> ls 'Net Sales'/'Sales Amount' # Quoted segments with a slash separator +``` + +Unterminated groups absorb to end of line, so a stray opening quote or bracket fails with an explicit error rather than splitting silently. + ## Built-in REPL commands These are handled by the REPL itself, not the regular command tree: diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 157c4c256..c72e83032 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -2,7 +2,7 @@ uid: te-cli title: Tabular Editor CLI (Limited Public Preview) author: Peer Grønnerup -updated: 2026-05-06 +updated: 2026-05-12 applies_to: products: - product: Tabular Editor 2 @@ -44,7 +44,7 @@ The CLI organizes more than 50 commands into 10 families. Each family maps to a | [Deployment & Refresh](xref:te-cli-commands#deployment-and-refresh) | Deploy to workspace, trigger refresh, incremental refresh | [`te deploy`](xref:te-cli-commands#deploy), [`te refresh`](xref:te-cli-commands#refresh), [`te incremental-refresh`](xref:te-cli-commands#incremental-refresh) | | [Testing](xref:te-cli-commands#testing) | Assertion tests, snapshots, A/B comparison | [`te test run`](xref:te-cli-commands#test-run) | | [Connection & Auth](xref:te-cli-commands#connection-and-auth) | Connect to workspaces, manage authentication and profiles | [`te connect`](xref:te-cli-commands#connect), [`te auth`](xref:te-cli-commands#auth-login--status--logout), [`te profile`](xref:te-cli-commands#profile-list--show--set--remove) | -| [Configuration](xref:te-cli-commands#configuration) | Settings and licensing | [`te config`](xref:te-cli-commands#config-show--paths--init--set), [`te license`](xref:te-cli-commands#license) | +| [Configuration](xref:te-cli-commands#configuration) | Settings and licensing | [`te config`](xref:te-cli-commands#config-show--paths--init--set) | | [Shell](xref:te-cli-commands#shell) | Interactive mode, shell completions | [`te interactive`](xref:te-cli-commands#interactive), [`te completion`](xref:te-cli-commands#completion) | See @te-cli-commands for a full command reference with syntax, options, and examples for each command. From a6c1900b2792517d019a438fbefc4f2f34f81f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maria=20Jos=C3=A9=20Ferreira?= <171664470+MariaJoseFF@users.noreply.github.com> Date: Wed, 13 May 2026 12:37:36 +0200 Subject: [PATCH 9/9] Update te-cli docs to reflect TE3 PR 3201 (CLI - Remove TE3 dependencies) (#317) * Update te-cli docs to reflect TE3 PR 3201 (CLI - Remove TE3 dependencies) Aligns te-cli-config, te-cli-commands, and te-cli-cicd with the cross-platform CLI's decoupled configuration model: - Schema: nested `bpa.*` object replaces flat `bpaRules`/`bpaOn*`; add `formatVersion`, `interactiveEditMode`, `queryLog`, `te3ExePath`; remove `te3DataDir`, `preferences`, `bpaMachineRules` - Path resolution: drop auto-detection of `%LocalAppData%\TabularEditor3`; new order is flag > env var > config > CWD fallback - New commands documented: `te bpa rules init`, `te bpa rules disable`, `te bpa rules enable`, `te macro init`, plus the built-in guard on `te bpa rules set / rm` - New flags documented: `te deploy --bpa-rules`, `te save --bpa-rules` - Environment variable renamed: `TE_BPA_RULES_PATH` -> `TE_BPA_PATH` - `TE_CONFIG` now honored by every `te config` operation - `te config paths` JSON output documented (emits null fields explicitly) - Added "Removed keys" reference table * Drop "Removed keys" section from te-cli-config No public preview build of the CLI was released with the older key names, so the migration table has no audience. Also removes the "Unknown or removed keys" wording and the [!NOTE] pointing at the deleted section. The `formatVersion` / `interactiveEditMode` paragraphs are preserved under a new "Other schema keys" heading. --------- --- content/features/te-cli/te-cli-cicd.md | 2 +- content/features/te-cli/te-cli-commands.md | 72 ++++++++++++- content/features/te-cli/te-cli-config.md | 112 ++++++++++++++------- 3 files changed, 148 insertions(+), 38 deletions(-) diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md index 0b4706072..361956891 100644 --- a/content/features/te-cli/te-cli-cicd.md +++ b/content/features/te-cli/te-cli-cicd.md @@ -167,7 +167,7 @@ te deploy ./model -s my-ws -d my-model --fix-bpa --force --ci github te deploy ./model -s my-ws -d my-model --skip-bpa --force --ci github ``` -See @te-cli-config for controlling the BPA gate globally via `bpaOnDeploy` / `bpaOnSave` config keys. +See @te-cli-config for controlling the BPA gate globally via `bpa.onDeploy` / `bpa.onSave` config keys. ## Refresh patterns diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index 91bda6dd4..6f3294c76 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -154,6 +154,7 @@ Save a model to disk. Use it to write a remote workspace model to local files, c - `--format ` — `tmdl`, `bim`, `te-folder`, `pbip`, `database.json`. Defaults to inferring from the loaded model (BIM source → BIM, TMDL `SemanticModel/` → TMDL under `definition/`). - `--force` — skip validation and overwrite existing output. Some refusals (ambiguous containers, multi-`SemanticModel` project roots) fire even under `--force`. - `--skip-bpa` / `--fix-bpa` — bypass or auto-fix the BPA gate. +- `--bpa-rules ` — repeatable; override `bpa.rules` from your CLI config for this single save. Built-in rules still apply unless `bpa.builtInRules` is `false`. - `--skip-validation` — skip DAX semantic analysis and validation for fast passthrough downloads. - `--supporting-files` — generate Fabric supporting files (`.platform`, `definition.pbism`). @@ -376,7 +377,17 @@ te bpa run --path Sales/Measures # Path filter applied to the matched tables ### bpa rules -List and inspect BPA rules from all sources (built-in, user, machine, model). +List, inspect, initialize, and toggle BPA rules. Built-in rules are read-only — to skip one without losing the rest, use `te bpa rules disable` (do not edit the built-in set directly). + +#### bpa rules list + +List rules from all sources (built-in, user, model). + +- (default) Active rules only. +- `--all` — include disabled and ignored rules. +- `--disabled` — only built-in rule IDs the user has disabled via `te bpa rules disable`. +- `--ignored` — only rules whose IDs appear in `BestPracticeAnalyzer_IgnoreRules` on the model. +- `--no-defaults` — exclude built-in rules from output. ```bash te bpa rules list # Active rules @@ -384,6 +395,48 @@ te bpa rules list --all # Include disabled and ignored rules te bpa rules list --ignored ``` +Disabled built-in rules are flagged with a `[disabled]` marker next to the rule ID. + +#### bpa rules init + +Create an empty BPA rules file (`[]`) at the configured path. Use this once before invoking `te bpa rules set` / `te bpa rules rm` against a path that does not yet exist. + +- `--force` — overwrite an existing file with `[]`. Required if the target file exists. +- `--rules-file ` — target file path. Can appear before or after the `init` subcommand. + +Path resolution (first match wins): `--rules-file` → `TE_BPA_PATH` env var → first entry of `bpa.rules[]` in your CLI config → `./BPARules.json` (current working directory). + +```bash +te bpa rules init +te bpa rules init --rules-file ./MyRules.json +te bpa rules init --force +``` + +#### bpa rules disable + +Disable an individual built-in BPA rule. The rule ID is added to `bpa.disabledBuiltInRuleIds` in your CLI config. Subsequent gate runs (deploy, save, mutation) and `te bpa run` skip the disabled rule. + +- Idempotent: running `disable` against an already-disabled rule succeeds without modifying the config. +- Errors with exit code `1` if `` is not a built-in rule. Use `te bpa rules list` to see valid built-in IDs. + +```bash +te bpa rules disable TE3_BUILT_IN_DATE_TABLE_EXISTS +``` + +#### bpa rules enable + +Re-enable a previously disabled built-in BPA rule. Removes the rule ID from `bpa.disabledBuiltInRuleIds`. + +- Errors with exit code `1` if `` is not currently in `bpa.disabledBuiltInRuleIds`. + +```bash +te bpa rules enable TE3_BUILT_IN_DATE_TABLE_EXISTS +``` + +#### bpa rules set / rm — built-in guard + +`te bpa rules set` and `te bpa rules rm` refuse to mutate built-in rule IDs. Attempting to do so exits with code `1` and points at `te bpa rules disable`. To customize a rule's behavior, copy it into your local rules file as a new rule with a different ID and disable the built-in. + ### vertipaq Analyze VertiPaq storage statistics. @@ -457,7 +510,7 @@ echo "Info(Model.Name);" | te script -e - ### macro -Manage and run Tabular Editor 3 macros from `MacroActions.json`. +Manage and run macros from a macros JSON file (typically `MacroActions.json`). The macros file is resolved in this order: `--macros ` → `TE_MACROS_PATH` env var → `macros` in CLI config → `./MacroActions.json`. ```bash te macro list # List macros @@ -466,6 +519,20 @@ te macro add # Add a macro te macro set # Update macro properties te macro rm # Remove a macro te macro sort # Sort and re-assign IDs +te macro init # Create an empty macros file at the resolved path +``` + +#### macro init + +Create an empty macros file (`{"Actions":[]}`) at the configured path. Use this once when the resolved macros file does not yet exist. + +- `--force` — overwrite an existing file. Required if the target exists. +- `--macros ` — target file path. Can appear before or after the `init` subcommand. + +```bash +te macro init +te macro init --macros ./project-macros.json +te macro init --force ``` `te macro run` accepts: @@ -492,6 +559,7 @@ Deploy a semantic model to Power BI, Fabric, or Azure Analysis Services. - `--deploy-connections`, `--deploy-partitions`, `--skip-refresh-policy`, `--deploy-roles`, `--deploy-role-members`, `--deploy-shared-expressions`, `--create-only`. - `--xmla ` — generate XMLA/TMSL script instead of deploying (`-` for stdout). - `--skip-bpa` / `--fix-bpa` — bypass or auto-fix the BPA gate. +- `--bpa-rules ` — repeatable; override `bpa.rules` from your CLI config for this single deploy. Built-in rules still apply unless `bpa.builtInRules` is `false`. - `--force` — skip interactive confirmation (required for CI). - `--ci ` — `vsts` or `github`. - `--profile ` — one-shot use of a saved @te-cli-auth profile. diff --git a/content/features/te-cli/te-cli-config.md b/content/features/te-cli/te-cli-config.md index 9ad32cf78..2bee23e92 100644 --- a/content/features/te-cli/te-cli-config.md +++ b/content/features/te-cli/te-cli-config.md @@ -16,7 +16,9 @@ applies_to: [!INCLUDE [te-cli-preview-notice](includes/te-cli-preview-notice.md)] -The Tabular Editor CLI reads optional configuration from a JSON file. Configuration controls three things: where the CLI looks for Tabular Editor 3's shared data files (Preferences, macros, BPA rules), behavioral defaults (BPA gates, auto-format, validation), and the list of saved connection profiles. +The Tabular Editor CLI reads optional configuration from a JSON file. Configuration controls three things: where the CLI looks for its own data files (macros, BPA rules), behavioral defaults (BPA gates, auto-format, validation), and the list of saved connection profiles. + +The CLI is self-contained — it does not read from or write to any Tabular Editor 3 desktop install path. BPA rules and macros files must be set explicitly via this config (or initialized on demand with `te bpa rules init` / `te macro init`); there is no auto-detection of `%LocalAppData%\TabularEditor3\` or `%ProgramData%\TabularEditor3\`. Most users don't need to edit the file directly — `te config show`, `te config set `, and `te profile set` cover the common operations. @@ -28,10 +30,12 @@ Resolution order: 2. `~/.config/te/config.json` (on Windows, `%USERPROFILE%\.config\te\config.json`). 3. No config file — the CLI uses built-in defaults. +`TE_CONFIG` is honored consistently by every config-file operation — `te config show`, `te config set`, `te config init`, and `te config paths` all read and write at the resolved path. This is primarily intended for testing, scripted installs, and per-environment configuration. + To create a default config: ```bash -te config init # Create ~/.config/te/config.json with defaults +te config init # Create config at TE_CONFIG (or ~/.config/te/config.json) te config init --force # Overwrite existing config ``` @@ -40,39 +44,48 @@ te config init --force # Overwrite existing config ```bash te config show # Display all settings te config show --output json # Machine-readable -te config paths # Show resolved TE3 file paths +te config paths # Show resolved macros and BPA rule paths ``` -`te config paths` resolves where the CLI will actually look for TE3 data files — useful when debugging missing macros or BPA rules. +`te config paths` resolves the files the CLI will actually use for macros and BPA rules — useful when debugging missing data files. The output shows two rows: `macros` (the resolved macros file path or `[not set]`) and `bpa.rules` (the first existing BPA rules file resolved by the path resolver, or `[not set]`). + +> [!NOTE] +> `te config paths` emits `null` fields explicitly in `--output json` mode (e.g., `{"macros": null, "bpa": {"rules": null}}`). Reporting resolution outcomes is the command's whole purpose, so `null` is a meaningful "tried but resolved to nothing" answer. `te config show --output json` strips null fields by default, so consumers should parse it tolerantly. ## Setting values ```bash te config set autoFormat true -te config set bpaOnDeploy false +te config set bpa.onDeploy false te config set hidePreviewNotice true te config set macros null # Clear a path override ``` -Unknown keys fail with an error that lists the valid keys. +Unknown keys fail with exit code `1` and an error that lists the valid keys. + +If no config file exists, `te config set` auto-creates one at the resolved path (`$TE_CONFIG` if set, otherwise `~/.config/te/config.json`) before applying the change. ## Full schema ```json { - "te3DataDir": null, - "preferences": null, + "formatVersion": 1, "macros": null, - "bpaRules": null, - "bpaMachineRules": null, - "autoFormat": false, "validateOnMutation": true, - "bpaOnMutation": false, - "bpaOnDeploy": true, - "bpaOnSave": true, "vertipaqOnRefresh": false, + "bpa": { + "rules": null, + "onDeploy": true, + "onSave": true, + "onMutation": false, + "builtInRules": true, + "disabledBuiltInRuleIds": null + }, + + "interactiveEditMode": "stage", + "formatOptions": { "useSemicolons": false, "shortFormat": false, @@ -83,6 +96,9 @@ Unknown keys fail with an error that lists the valid keys. "spinner": true, "debug": false, + "queryLog": null, + "te3ExePath": null, + "profiles": {} } ``` @@ -91,34 +107,51 @@ Unknown keys fail with an error that lists the valid keys. | Key | Meaning | | -- | -- | -| `te3DataDir` | Base directory used for TE3 file discovery when individual paths below are not set. Defaults to `%LOCALAPPDATA%\TabularEditor3` (Windows) or the equivalent auto-detected location on macOS/Linux. | -| `preferences` | Explicit path to `Preferences.json`. | -| `macros` | Explicit path to `MacroActions.json`. | -| `bpaRules` | Explicit path to user-level `BPARules.json`. | -| `bpaMachineRules` | Explicit path to machine-level `BPARules.json`. | +| `macros` | Explicit path to a macros JSON file (typically `MacroActions.json`). Resolved by `te macro` commands. | +| `bpa.rules` | Ordered list of BPA rule files / URLs the gate loads. The gate uses every existing entry. Comma-separated values on `te config set bpa.rules ...` are split into the array. | +| `te3ExePath` | Explicit path to the TE3 desktop executable (`TabularEditor.exe`). Used **only** by `te open`; safe to leave unset on Linux/macOS or when you don't use `te open`. | ### Path resolution priority -For each TE3 file (Preferences, macros, BPA rules), the CLI resolves the path in this order: +For each user-provided file (macros, BPA rules), the CLI resolves the path in this order: -1. **CLI config override** — the explicit entry above (`preferences`, `macros`, …). -2. **Environment variable** — e.g., `TE_MACROS_PATH`, `TE_BPA_RULES_PATH`. -3. **`te3DataDir`** — joined with the default filename. -4. **Auto-detect** — Windows `%LOCALAPPDATA%\TabularEditor3\...`, or the equivalent on macOS/Linux; on macOS we also probe a Parallels-style mapping if present. +1. **Command-line flag** — `--macros ` for macro commands; `--bpa-rules ` for the deploy/save gate; `--rules-file ` for `te bpa rules` subcommands. +2. **Environment variable** — `TE_MACROS_PATH` for macros, `TE_BPA_PATH` for BPA rules. +3. **CLI config** — `macros` for macros, the first existing entry of `bpa.rules[]` for BPA rules. +4. **Working-directory fallback** — `./MacroActions.json` for `te macro init`, `./BPARules.json` for `te bpa rules init`. -Run `te config paths` to see which file the CLI actually resolved for each TE3 asset. +The CLI does not auto-detect any TE3 install location — configure these explicitly or use the `init` commands. + +Run `te config paths` to see which file the CLI actually resolved. ### Behavioral defaults +All BPA-related settings live under the `bpa` object and are addressed via dotted keys on `te config set`. + | Key | Default | Description | | -- | -- | -- | | `autoFormat` | `false` | Run DAX Formatter on modified expressions after `te add` / `te set` / `te mv` / `te macro run`. | | `validateOnMutation` | `true` | Validate `Table[Column]` references after any mutating command. | -| `bpaOnMutation` | `false` | Run BPA after mutating commands. | -| `bpaOnDeploy` | `true` | Run BPA as a gate before `te deploy`. Bypass with `--skip-bpa`. | -| `bpaOnSave` | `true` | Run BPA as a gate before `te save`. Bypass with `--skip-bpa`. | +| `bpa.onMutation` | `false` | Run BPA after mutating commands (`set`, `add`, `mv`, `rm`, `macro run`). | +| `bpa.onDeploy` | `true` | Run BPA as a gate before `te deploy`. Bypass with `--skip-bpa`. | +| `bpa.onSave` | `true` | Run BPA as a gate before `te save`. Bypass with `--skip-bpa` or `--force`. | +| `bpa.builtInRules` | `true` | Include the built-in BPA rule set whenever the gate runs. | +| `bpa.disabledBuiltInRuleIds` | `null` | IDs of individual built-in rules to exclude from the gate. Mutated by `te bpa rules disable` / `te bpa rules enable`. | | `vertipaqOnRefresh` | `false` | Capture VertiPaq stats after a successful refresh. | +```bash +te config set bpa.rules "/etc/te/team.json,/etc/te/strict.json" +te config set bpa.onDeploy true +te config set bpa.builtInRules false +te config set bpa.disabledBuiltInRuleIds "TE3_BUILT_IN_DATE_TABLE_EXISTS,TE3_BUILT_IN_HIDE_FOREIGN_KEYS" +``` + +### Other schema keys + +`formatVersion` is set by the CLI when writing the file and is **not** user-settable via `te config set`. The CLI refuses to load a file whose `formatVersion` is higher than the build understands, so an older CLI cannot silently clobber a newer config. + +`interactiveEditMode` comes from the interactive-staging feature (`stage` / `save` / `revert`); it can be set via `te config set interactiveEditMode ` and is documented in that feature's release notes. + ### Format options Applied whenever the CLI invokes the DAX Formatter (for `te format` and, when enabled, `autoFormat` on mutations). @@ -152,15 +185,17 @@ te profile set prod --auto-format true The BPA gate is the safety net that prevents a model with rule violations from being saved or deployed. It runs automatically when: -- `te deploy` executes — unless `--skip-bpa` is passed or `bpaOnDeploy` is `false`. -- `te save` executes — unless `--skip-bpa` is passed or `bpaOnSave` is `false`. -- `te add` / `te set` / `te mv` / `te macro run` executes — only when `bpaOnMutation` is `true`. +- `te deploy` executes — unless `--skip-bpa` is passed or `bpa.onDeploy` is `false`. +- `te save` executes — unless `--skip-bpa` (or `--force`) is passed or `bpa.onSave` is `false`. +- `te add` / `te set` / `te mv` / `te macro run` executes — only when `bpa.onMutation` is `true`. + +The gate loads BPA rules from `bpa.rules` plus, by default, the built-in rule set (controlled by `bpa.builtInRules`). Built-in rules can be individually excluded via `bpa.disabledBuiltInRuleIds` — managed with `te bpa rules disable ` / `te bpa rules enable `. When the gate fires and finds violations at severity ≥ `error`, the command fails with exit code `1` and a summary of the violations. Options to resolve: - `--fix-bpa` — apply the rule's `fixExpression` in memory for the deploy/save artifact; source files are not modified. - `--skip-bpa` — disable the gate for this one command. -- `.te-bpa.json` in the model directory — project-local BPA gate configuration (replacement for editing Preferences). +- `--bpa-rules ` — repeatable; override `bpa.rules` for this single `te deploy` or `te save` invocation. Built-in rules still apply unless `bpa.builtInRules` is `false`. Run `te bpa run` independently to preview the gate's behavior without deploying: @@ -169,6 +204,12 @@ te bpa run ./model --fail-on error te bpa run ./model --fix --save # Apply fixes to the source ``` +### Built-in BPA rules + +The CLI ships a single canonical set of built-in BPA rules embedded as a JSON resource. Built-in rules are read-only — `te bpa rules set` and `te bpa rules rm` refuse to mutate built-in IDs and point users at `te bpa rules disable` instead. To customize a built-in rule's behavior, copy it into your local rules file as a new rule with a different ID and disable the built-in. + +Both `bpa.builtInRules` and `bpa.disabledBuiltInRuleIds` apply consistently to the deploy/save/mutation gate **and** the manual `te bpa run` command — disabling a rule once via `te bpa rules disable` excludes it everywhere. + ## Post-mutation behavior When you run a mutating command (`te add`, `te set`, `te mv`, `te replace --save`, `te macro run`), the CLI performs these checks automatically: @@ -176,7 +217,7 @@ When you run a mutating command (`te add`, `te set`, `te mv`, `te replace --save 1. **TOM errors** are always surfaced — invalid DAX or M in measures, columns, partitions, calculation items. These always fail the command. 2. **Schema validation** (`validateOnMutation`, default `true`) — verifies that `Table[Column]` references in DAX still resolve. Cross-check of metadata consistency. 3. **DAX auto-format** (`autoFormat`, default `false`) — when enabled, formats any expressions touched by the mutation via the built-in DAX Formatter. -4. **BPA on mutation** (`bpaOnMutation`, default `false`) — when enabled, runs BPA after the mutation and warns/fails based on `--fail-on`. +4. **BPA on mutation** (`bpa.onMutation`, default `false`) — when enabled, runs BPA after the mutation and warns/fails based on `--fail-on`. Disable a check with `te config set false`, or scope the relaxation to a specific environment via a profile. @@ -184,11 +225,12 @@ Disable a check with `te config set false`, or scope the relaxation to a s | Variable | Purpose | | -- | -- | -| `TE_CONFIG` | Path to an alternative config file. Overrides `~/.config/te/config.json`. | +| `TE_CONFIG` | Path to an alternative config file. Honored by every `te config` operation (`show`, `set`, `init`, `paths`). | | `TE_DEBUG` | Set to `1` to enable debug logging globally (same as `--debug` or `debug: true` in config). | | `TE_COMPAT` | Set to `te2` to force TE2-compatibility mode — see @te-cli-migrate. | | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_TENANT_ID` | Service principal credentials, used by `--auth env`. | -| `TE_MACROS_PATH`, `TE_BPA_RULES_PATH`, ... | Per-file overrides for TE3 asset paths (second in resolution order — see above). | +| `TE_MACROS_PATH` | Per-invocation override for the macros file path (second in resolution order — see above). | +| `TE_BPA_PATH` | Per-invocation override for the BPA rules file path used by `te bpa rules` subcommands. | ## Related pages