diff --git a/content/features/te-cli/includes/te-cli-preview-notice.md b/content/features/te-cli/includes/te-cli-preview-notice.md index 6c4131be9..ced47085a 100644 --- a/content/features/te-cli/includes/te-cli-preview-notice.md +++ b/content/features/te-cli/includes/te-cli-preview-notice.md @@ -1,2 +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. +> 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. diff --git a/content/features/te-cli/te-cli-auth.md b/content/features/te-cli/te-cli-auth.md index d4e174116..bd92d2139 100644 --- a/content/features/te-cli/te-cli-auth.md +++ b/content/features/te-cli/te-cli-auth.md @@ -110,6 +110,9 @@ te connect ./my-model # Connect to a running Power BI Desktop instance (Windows only) te connect --local +# Filter by report name when multiple Power BI Desktop instances are running +te connect --local my-report + # Show the active connection te connect diff --git a/content/features/te-cli/te-cli-automation.md b/content/features/te-cli/te-cli-automation.md index 0b6211f88..53c76fb79 100644 --- a/content/features/te-cli/te-cli-automation.md +++ b/content/features/te-cli/te-cli-automation.md @@ -27,11 +27,11 @@ Use `--output-format` to switch any command between text (human-readable) and ma | `text` (default) | Human-readable use | Plain text on stdout regardless of whether the stream is a TTY or piped. | | `json` | Machine-readable use | Always valid JSON to stdout. Use `--error-format json` if you also want machine-readable errors on stderr. | | `csv` | Tabular results (`query`, `bpa run`, `bpa rules`, `vertipaq`, `validate`, `test`, `refresh`, `profile list`, `session list`, `find`, `replace`, `get`, `ls`) | RFC 4180 escaping. | -| `tmsl` (alias `bim`) | Whole-object TMSL/BIM serialization | Accepted by `te get` and `te ls`. | +| `tmsl` (alias `bim`) | Whole-object TMSL/BIM serialization | Accepted by `te get` and `te list`. | | `tmdl` | Whole-object TMDL serialization | Accepted by `te get` only (single object). | ```bash -te ls --output-format json +te list --output-format json te query -q "EVALUATE VALUES('Date'[Year])" --output-format csv te bpa run --output-format json ``` @@ -54,7 +54,7 @@ Every `te` command exits with a predictable status code so callers can branch on | Exit | Meaning | | -- | -- | | `0` | Success. | -| `1` | Generic failure - invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity ≥ error. For `te diff`: differences found (like the `diff`/`cmp` convention). | +| `1` | Generic failure - invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error. For `te diff`: differences found (like the `diff`/`cmp` convention). | | `2` | `te diff` only: an error occurred while comparing, so the difference status is unknown. | Combine exit codes with `--ci ` annotations and `--trx ` to surface rich failure information in CI - see @te-cli-cicd. @@ -64,7 +64,7 @@ Combine exit codes with `--ci ` annotations and `--trx ` to 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-format json | jq '.[] | .name' +te list --output-format json | jq '.[] | .name' te vertipaq --output-format json > stats.json ``` @@ -151,7 +151,7 @@ Compose commands with pipes and `jq`. The CLI's text output is colorized for hum ```bash # Count measures per table -te ls --type measure --output-format json \ +te list --type measure --output-format json \ | jq -r '.[] | .table' \ | sort | uniq -c | sort -rn ``` @@ -178,10 +178,10 @@ The resulting TMSL can be reviewed in a pull request, committed, executed by the A handful of small idioms that come up often when composing `te` commands in scripts or pipelines: -- **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. +- **Idempotent creates and removes.** `te add Sales/Marker -t Measure -i "0" --if-not-exists --save` and `te remove 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`. The model-level containers (`te ls Measures`, `te ls Columns`) compose well with this for whole-model sweeps. +- **Path-only output.** `te list --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 list Measures`, `te list 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. diff --git a/content/features/te-cli/te-cli-cicd.md b/content/features/te-cli/te-cli-cicd.md index c5676b754..0ccd379b2 100644 --- a/content/features/te-cli/te-cli-cicd.md +++ b/content/features/te-cli/te-cli-cicd.md @@ -166,7 +166,7 @@ steps: `te deploy` and `te save` run the Best Practice Analyzer as a pre-flight gate by default. Three behaviors are worth determining 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. +- **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. diff --git a/content/features/te-cli/te-cli-commands.md b/content/features/te-cli/te-cli-commands.md index 727993013..4d1acce42 100644 --- a/content/features/te-cli/te-cli-commands.md +++ b/content/features/te-cli/te-cli-commands.md @@ -30,8 +30,8 @@ te bpa run --help # Help for a command with subcommands Object addressing in the CLI uses a single grammar that's shared across every command. Two flavours of path appear in the reference below: -- **``** - 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. +- **``** - resolves to **exactly one** object or container. Used by commands that operate on a single target: `te get`, `te set`, `te add`, `te remove`, `te move`, `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 list`, `te bpa run --path`, and other inspection-style commands. Both path forms share the same syntax rules; they differ in only two places: @@ -42,9 +42,9 @@ Both path forms share the same syntax rules; they differ in only two places: 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 +- `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. @@ -100,22 +100,22 @@ Quote a segment to force literal-name matching when a real object name happens t ### 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. +Filter paths add a single wildcard character - `*` - that matches any run of characters within one segment (greedy, single-segment). Wildcards are how `te list` 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* +te list 'Sa*' # Tables whose name starts with Sa +te list 'Sales/*Amount' # Children of Sales whose name ends with Amount +te list '*/Amount' # An Amount column/measure across every table +te list '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. +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 list 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 list 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 without hierarchies) emit a simply "nothing here" hint rather than an error. +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 list Hierarchies` on a model without hierarchies) emit a simply "nothing here" hint rather than an error. ## Global options @@ -123,12 +123,12 @@ These flags are available on every command and can be used before or after the s | Option | Description | | -- | -- | -| `-m, --model ` | Path to semantic model (TMDL folder, `.bim` file, or TE folder). | +| `-m, --model ` | Path to semantic model (TMDL folder, `.bim` file, `database.json` folder, or `.SemanticModel` 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`, `spn`, `env`, `managed-identity` (default: `auto`). | -| `--output-format ` | Stdout format: `text` (default), `json`, `csv`, `tmsl` (alias `bim`), `tmdl`. `csv` is honored by commands that emit tabular data; `tmsl`/`tmdl` only by `te get` and `te ls` for whole-object serialization. Commands reject formats they don't support. | +| `--output-format ` | Stdout format: `text` (default), `json`, `csv`, `tmsl` (alias `bim`), `tmdl`. `csv` is honored by commands that emit tabular data; `tmsl`/`tmdl` only by `te get` and `te list` for whole-object serialization. Commands reject formats they don't support. | | `--error-format ` | Stderr format for errors, warnings, and hints: `text` (default) or `json`. Other values fall back to text. Independent of `--output-format`, so you can pair JSON stdout with plain-text errors (or vice versa). | | `--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. | @@ -140,11 +140,17 @@ For commands that read a model, the resolution order is: positional `` argument → `--model` global flag → `--server`/`--database` (remote) → active connection from `te connect` → `--recent`. +> [!NOTE] +> **Mistyped options are rejected up front.** If you pass a `--flag` that isn't recognised on the command you invoked, the CLI exits with an actionable error rather than silently absorbing the token as a positional argument. This catches typos like `--force ` accidentally becoming `--forec` in CI scripts. + +> [!NOTE] +> **Dotted server names.** `-s`/`--server` treats a dotted name (e.g. `Sales.2026`) as an Analysis Services server hostname, not a Power BI workspace. A warning fires when the CLI has to make this call, with a hint to append `.Workspace` (e.g. `Sales.2026.Workspace`) or use a full `powerbi://` URL if you meant the Power BI workspace. Applies to `te connect`, `te deploy`, `te refresh`, `te query`, `te vertipaq`, and `te test run`. + ## Model I/O ### load -Load a semantic model and display a summary of the model — name, compatibility level, and high-level object counts (tables, measures, columns). +Load a semantic model and display a summary of the model - name, compatibility level, and high-level object counts (tables, measures, columns). ```bash te load ./model # TMDL folder @@ -158,8 +164,8 @@ Save a model to disk. Use it to write a remote workspace model to local files, c `te save` accepts: -- `-o, --output-path ` - target file or folder. **Optional** - when omitted, `te save` writes back to the source location, preserving the original format. -- `--serialization ` - `tmdl`, `bim`, `te-folder`, `pbip`, `database.json`. Defaults to inferring from the loaded model (BIM source → BIM, TMDL `SemanticModel/` → TMDL under `definition/`). +- `-o, --output-path ` - target file or folder. **Optional** - when omitted, `te save` writes back to the source location, preserving the original format. The file extension also drives format inference: `.bim` writes a single-file BIM, `.json` writes a `database.json` folder, and a bare path writes a TMDL folder. +- `--serialization ` - `tmdl`, `bim` (alias `tmsl`), `database.json`, `pbip`. When omitted, the format is inferred from the `-o` path extension (or from the loaded model when `-o` is omitted entirely). - `--force` - skip validation and overwrite existing output. Some refusals (ambiguous containers, multi-`SemanticModel` project roots) fire even under `--force`. - `--skip-bpa` - bypass the BPA gate entirely. - `--fix-bpa` - auto-fix BPA violations where rules define a fix expression. @@ -179,10 +185,12 @@ te save -o ./out -s my-workspace -d my-model --skip-validation # Fast download ### open -Open a model in Tabular Editor 3 Desktop. **Windows only** (requires TE3 to be installed). +Open a model in Tabular Editor 3 Desktop. **Windows only** (requires TE3 to be installed). With no arguments, launches TE3 with a blank workspace. ```bash -te open ./my-model +te open # Launch TE3 with a blank workspace +te open ./my-model # Open a TMDL folder in TE3 +te open ./model.bim # Open a BIM file in TE3 ``` ### init @@ -195,7 +203,7 @@ Create a new empty semantic model at the given path. Defaults to a TMDL model in - `--compatibility-mode ` - `PowerBI` (default) or `AnalysisServices`. - `--compatibility-level ` (alias `--compat`) - compatibility level. Defaults to `1702` when the mode is `PowerBI`, `1500` otherwise. See @update-compatibility-level. - `--name ` - model/database name (default: the directory name). -- `--serialization ` - `tmdl` (default), `bim`, `te-folder`, `pbip`. +- `--serialization ` - `tmdl` (default), `bim` (alias `tmsl`), `database.json`, `pbip`. - `--force` - replace any existing file or directory at the target path. ```bash @@ -213,14 +221,18 @@ Set a property on a model object. Accepts a ``. `te set` accepts: -- `-q ` - property name (e.g., `expression`, `formatString`, `description`, `isHidden`). -- `-i ` - value (use `-` to read from stdin). +- `-q ` - property name (e.g., `expression`, `formatString`, `description`, `isHidden`). **Repeatable** - pair each `-q` with a following `-i` to set multiple properties in one command. +- `-i ` - value (use `-` to read from stdin). One `-i` per `-q`. +- `-t, --type ` - disambiguation when the same path could resolve to multiple object kinds (`Measure`, `Column`, `CalculatedColumn`, `Hierarchy`, `Calendar`, `Partition`, `CalculationItem`). - `--save` / `--save-to ` - persist changes. +- `--serialization ` - override the serialization when saving (`tmdl`, `bim` (alias `tmsl`), `database.json`). +- `--force` - save even if the mutation introduces DAX validation errors. ```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 +te set Sales/Amount -q formatString -i "#,0" -q description -i "Net sales" --save # Multi-property ``` ### add @@ -230,7 +242,15 @@ Add an object to the model. Pass a `` for the new object (the parent must `te add` accepts: - `-t, --type ` - object type. Common values: `Table`, `Measure`, `Column`, `CalculatedColumn`, `Hierarchy`, `Role`, `Perspective`, `Culture`, `CalculationGroup`, `CalculationItem`. Tab-completion is supported; the full list can be retrieved by running `te add --help`. +- `-i ` - expression or value to assign to the new object (DAX for measures/calculated columns, M for partitions, etc.). Pair with `-q` to set additional properties on the new object in the same command. +- `-q ` - additional property to set on the new object (repeatable; pairs with `-i`). +- `--file ` - read the expression for `-i` from a file instead of inline. +- `--mode ` - storage mode for new tables: `import` (default), `directQuery`, `dual`, `directLake`. - `--if-not-exists` - exit `0` without error if the object already exists. Use this for idempotent CI/CD pipelines. +- `--save` / `--save-to ` - persist changes. +- `--serialization ` - override the serialization when saving (`tmdl`, `bim` (alias `tmsl`), `database.json`). +- `--source-type ` - initial partition source type on a new table: `m`, `query`, or `calculated`. Overrides heuristic detection. `calculated` is only valid with `-t CalculatedTable`. +- `--force` - save even if the mutation introduces DAX validation errors. ```bash te add Sales/Revenue -t Measure -i "SUM(Sales[Amount])" --save @@ -243,32 +263,42 @@ te add Roles/Reader -t Role --save # New 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 -Remove an object. Checks dependents by default to prevent breaking existing references. +Remove an object. Checks dependents by default to prevent breaking existing references. (Alias: `rm`.) -`te rm` accepts: +`te remove` accepts: -- `` — positional argument: the object to remove. -- `--force` — bypass the dependents check. -- `--if-exists` — exit `0` without error if the object doesn't exist. Use this for idempotent CI/CD pipelines. -- `--dry-run` — preview the removal without applying it. -- `--save` — persist the change to the loaded model. +- `` - positional argument: the object to remove. +- `-t, --type ` - disambiguate when the path matches multiple table-children (e.g., a column and a hierarchy with the same name). +- `--force` - bypass the dependents check. +- `--if-exists` - exit `0` without error if the object doesn't exist. Use this for idempotent CI/CD pipelines. +- `--dry-run` - preview the removal without applying it. +- `--save` / `--save-to ` - persist the change. +- `--serialization ` - override the serialization when saving (`tmdl`, `bim` (alias `tmsl`), `database.json`). ```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 +te remove Sales/Revenue --save +te remove "'Sales'[Revenue]" --save # DAX form +te remove Sales/Revenue --dry-run # Preview only +te remove Sales/OldMeasure --if-exists --save # Idempotent ``` -### mv +### move + +Move or rename a model object. Both source and destination are `` arguments. (Aliases: `mv`, `rename`.) + +`te move` accepts: -Move or rename a model object. Both source and destination are `` arguments. +- `-t, --type ` - disambiguate when the source path matches multiple object kinds (e.g., a column and a hierarchy with the same name). +- `--save` / `--save-to ` - persist the change. +- `--serialization ` - override the serialization when saving (`tmdl`, `bim` (alias `tmsl`), `database.json`). +- `--force` - save even if the mutation introduces DAX validation errors. ```bash -te mv Sales/Revenue Finance/Revenue --save # Move measure to another table -te mv Sales/Revenue Sales/TotalRevenue --save # Rename measure +te move Sales/Revenue Finance/Revenue --save # Move measure to another table +te move Sales/Revenue Sales/TotalRevenue --save # Rename measure +te move Sales/Date Sales/CalendarDate -t Hierarchy --save # Disambiguate hierarchy from column ``` ### replace @@ -283,7 +313,7 @@ Find and replace text across model objects. Dry-run by default; add `--save` to - `--dry-run` - preview changes without applying. Default behavior. - `--save` - persist the mutation to the source location. Mutually exclusive with `--revert` and `--stage`. - `--save-to ` - save to a different path (implies `--save`). -- `--serialization ` - model serialization: `tmdl`, `bim`, `te-folder`. +- `--serialization ` - model serialization: `tmdl`, `bim` (alias `tmsl`), `database.json`. - `--force` - save even if the replacement introduces DAX validation errors. `--in expressions` walks every expression-bearing property: @@ -304,31 +334,31 @@ te replace "SUM" "SUMX" --regex --in expressions --save ## Inspection -### ls +### list -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. +List objects with filesystem-like navigation. Takes a `` argument supporting wildcards. Both model-level containers and table-scoped containers are supported - see the [container keyword table](#containers-and-keywords) above for the full list. (Alias: `ls`.) -`te ls` accepts: +`te list` accepts: - `--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-format tmsl` (alias `bim`) - emit the matching objects as a TMSL/BIM script. Useful for `te ls Tables --output-format bim > tables.json`. `--output-format tmdl` is not supported by `ls` (TMDL is single-object only - use `te get`). +- `--output-format tmsl` (alias `bim`) - emit the matching objects as a TMSL/BIM script. Useful for `te list Tables --output-format bim > tables.json`. `--output-format tmdl` is not supported by `ls` (TMDL is single-object only - use `te get`). ```bash -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-format bim > tables.json # All tables emitted as TMSL/BIM +te list # All tables in the model +te list Sales # All children of Sales (columns + measures + hierarchies + partitions) +te list Sales/Measures # Just Sales's measures +te list 'Sales/*Amount' # Children of Sales whose name ends with Amount +te list 'Sa*' # Tables whose name starts with Sa (no auto-expansion) +te list '*/Amount' # An Amount column/measure across every table +te list 'Roles/Re*/Members' # Members of every role matching Re* +te list Sales/Geography/Levels # All levels of the Geography hierarchy +te list "'Net Sales'/'Sales Amount'" # Quote names containing spaces +te list Measures --paths-only # One Table/Measure per line for piping +te list --type measure # Same as `te list Measures` +te list Measures --no-multiline # Wide table with column dividers, single-line DAX +te list Tables --output-format bim > tables.json # All tables emitted as TMSL/BIM ``` ### get @@ -342,7 +372,7 @@ Get properties of a model object. Takes a ``. - `--output-format tmsl` (alias `bim`) - emit the resolved object as TMSL/BIM JSON. - `--output-format 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. +`te get` and `te list` 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 @@ -380,6 +410,12 @@ Compare two models for structural differences. Returns the following exit codes: ```bash te diff ./model-v1 ./model-v2 te diff old.bim new.bim + +# Branch on exit code (POSIX sh): +te diff ./a ./b; case $? in 0) echo same;; 1) echo different;; *) echo error;; esac + +# Branch on exit code (PowerShell): +te diff ./a ./b; switch ($LASTEXITCODE) { 0 { 'same' } 1 { 'different' } default { 'error' } } ``` ### deps @@ -426,6 +462,9 @@ te validate --ci github --trx results.trx te validate --errors-only # Hide warnings and anti-pattern hints ``` +> [!NOTE] +> `te validate` does not support `--output-format csv` - CSV is rejected up front with an actionable error rather than producing a partial result. Use `text` or `json` for validation output. + ### bpa run Run Best Practice Analyzer rules against a model. @@ -444,8 +483,8 @@ Run Best Practice Analyzer rules against a model. - `--fix` - apply fix expressions to auto-fix violations where possible. - `--save` - save the model back to source after applying fixes. - `--save-to ` - save the model to a different path after applying fixes. -- `--serialization ` - model serialization: `tmdl`, `bim`, `te-folder`. -- `--fail-on ` - failure threshold: `error` (default) or `warning`. Exits with code `1` when violations meet the threshold. +- `--serialization ` - model serialization: `tmdl`, `bim` (alias `tmsl`), `database.json`. +- `--fail-on ` - failure threshold: `error` (default) or `warning`. Exits with code `1` when violations meet the threshold. Rule-loading or evaluation errors (invalid expressions, unreadable rule files) also cause a non-zero exit regardless of `--fail-on`. - `--ci ` - emit CI logging commands to stderr: `vsts` (Azure DevOps), `github` (GitHub Actions). - `--trx ` - write results as a VSTEST `.trx` file to the specified path. - `--no-multiline` - collapse multi-line cell content in the violations table to a single line. Text output only. @@ -480,7 +519,7 @@ Rules loaded: 41 from 1 file(s) from bpa.rules config + built-in defaults + mode ### bpa rules -Manage BPA rule collections — list, inspect, initialize, and toggle rules in your local rules file or in model annotations. 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). +Manage BPA rule collections - list, inspect, initialize, and toggle rules in your local rules file or in model annotations. 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). Subcommands: @@ -492,7 +531,7 @@ Subcommands: | `ignore [model]` | Add a rule to the model's ignore list. | | [`init`](#bpa-rules-init) | Create an empty BPA rules file at the resolved path. | | [`list`](#bpa-rules-list) | List BPA rules from all sources with status. | -| `rm [model]` | Remove a BPA rule. | +| `remove [model]` (alias `rm`) | Remove a BPA rule. | | `set [model]` | Update a BPA rule's properties. | | `unignore [model]` | Remove a rule from the model's ignore list. | @@ -502,7 +541,7 @@ All `te bpa rules` subcommands accept: - `--model-rules` - operate on rules embedded in the model annotation instead of a file. > [!IMPORTANT] -> `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 built-in rule's behavior, disable the built-in and add a custom copy with a different ID: +> `te bpa rules set` and `te bpa rules remove` 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 built-in rule's behavior, disable the built-in and add a custom copy with a different ID: > > ```bash > te bpa rules disable TE3_BUILT_IN_DATE_TABLE_EXISTS @@ -531,7 +570,7 @@ Disabled built-in rules are flagged with a `[disabled]` marker next to the rule #### 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. +Create an empty BPA rules file (`[]`) at the configured path. Use this once before invoking `te bpa rules set` / `te bpa rules remove` against a path that does not yet exist. `te bpa rules init` accepts: @@ -546,11 +585,44 @@ te bpa rules init --rules-file ./MyRules.json te bpa rules init --force ``` +#### bpa rules add / set / remove / ignore / unignore + +Mutate the rules file (`add`, `set`, `remove` (alias `rm`)) or model-embedded ignore list (`ignore`, `unignore`). All three mutating subcommands operate on `--rules-file ` or `--model-rules` and refuse to touch built-in rule IDs. + +- `te bpa rules add ` - create a new rule. Pass each property as a named option: + - `--name ` - human-readable rule name (required). + - `--scope ` - comma-separated object kinds the rule applies to: `Measure`, `Column`, `Table`, `Hierarchy`, `Partition`, `Relationship`, `Role`, `Perspective`, `Culture`, etc. (required). + - `--expression ` - Dynamic LINQ predicate. Returns `true` for objects that violate the rule (required). + - `--category ` - grouping label (e.g. `Performance`, `Naming`, `DAX Expressions`). + - `--severity <1|2|3>` - `1` (info), `2` (warning, default), `3` (error). + - `--description ` - user-facing description shown when the rule fires. + - `--fix-expression ` - Dynamic LINQ expression used by `te bpa run --fix` to auto-remediate. +- `te bpa rules set ` - update properties on an existing rule. Uses `-q -i ` pairs (repeatable). Property names: `name`, `expression`, `scope`, `category`, `severity`, `description`, `fixExpression`. +- `te bpa rules remove ` - remove a rule. +- `te bpa rules ignore ` - add a rule ID to the model's `BestPracticeAnalyzer_IgnoreRules` annotation. +- `te bpa rules unignore ` - remove a rule ID from the model's ignore list. + +```bash +# Add a rule: measures that are not hidden and have no description +te bpa rules add MEASURE_NEEDS_DESCRIPTION \ + --name "Measures should have a description" \ + --scope Measure \ + --expression "not IsHidden and string.IsNullOrEmpty(Description)" \ + --severity 2 \ + --category Metadata + +# Update severity on an existing rule +te bpa rules set MEASURE_NEEDS_DESCRIPTION -q severity -i 3 + +# Remove the rule +te bpa rules remove MEASURE_NEEDS_DESCRIPTION +``` + #### 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. -The command is idempotent — running `disable` against an already-disabled rule succeeds without modifying the config. It exits with code `1` if `` is not a built-in rule; use `te bpa rules list` to see valid built-in IDs. +The command is idempotent - running `disable` against an already-disabled rule succeeds without modifying the config. It exits with 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 @@ -570,6 +642,7 @@ Analyze VertiPaq storage statistics. `te vertipaq` accepts: +- `` - optional positional argument: a table name to filter the analysis to a single table. - `--columns`, `--relationships`, `--partitions`, `--all`. - `--detail` - show expanded columns (data/dict/hierarchy size breakdown, encoding, segments). - `--fields ` - comma-separated fields to display (e.g., `--fields name,card,size,%tbl,%db,bar`). Available fields vary by view. @@ -577,10 +650,12 @@ Analyze VertiPaq storage statistics. - `--import ` - load a previously exported `.vpax` file and analyze it offline. - `--obfuscate` - obfuscate names and expressions in exported VPAX. - `--top `, `--stats`, `--annotate`, `--save`. +- `--auth ` - auth method override when connecting to a remote model. ```bash -te vertipaq # Columns by size (default) -te vertipaq --all # Tables, columns, relationships, partitions +te vertipaq # Columns by size (default) +te vertipaq Sales # Stats limited to the Sales table +te vertipaq --all # Tables, columns, relationships, partitions te vertipaq --export stats.vpax te vertipaq --import stats.vpax # Analyze offline ``` @@ -615,7 +690,8 @@ Execute a DAX query against a deployed model. `te query` accepts: -- `-q, --query ` - inline query. +- `` - positional argument: the DAX query to execute. Equivalent to passing `-q`. Use whichever shape reads better; explicit `-q` wins if both are supplied. +- `-q, --query ` - inline query (named-flag form of the positional above). - `--file ` - query from file. - `--limit ` - default 100. - `-o, --output-file ` - write results to file (`.csv`, `.tsv`, `.json`, `.dax`). @@ -623,7 +699,8 @@ Execute a DAX query against a deployed model. - `--no-validate` - skip pre-execution DAX semantic validation. ```bash -te query -q "EVALUATE TOPN(5, 'Sales')" -s my-ws -d my-model +te query "EVALUATE TOPN(5, 'Sales')" -s my-ws -d my-model # Positional DAX +te query -q "EVALUATE TOPN(5, 'Sales')" -s my-ws -d my-model # Named-flag form te query --file query.dax --output-format json ``` @@ -684,10 +761,24 @@ Subcommands: | [`run `](#macro-run) | Run a macro. | | `add ` | Add a macro. | | `set ` | Update macro properties. | -| `rm ` | Remove a macro. | +| `remove ` (alias `rm`) | Remove a macro. | | `sort` | Sort and re-assign IDs. | | [`init`](#macro-init) | Create an empty macros file at the resolved path. | +#### macro add / set / remove + +Mutate the macros file (`add`, `set`, `remove` (alias `rm`)). All three operate on `--macros ` (or the resolved macros file). + +- `te macro add ` - create a new macro. Provide the script body via `-e ""` (inline) or `-s ` (script file). Optional: `--tooltip `, `--contexts ` (where the macro applies, e.g., `Table,Measure`), `--enabled true|false`. +- `te macro set ` - update macro properties. Use `-q -i ` pairs (repeatable). Property names: `name`, `execute`, `enabled`, `tooltip`, `validContexts`. +- `te macro remove ` - remove a macro. + +```bash +te macro add MyMacro -e "Info(Selected.Measure.Name);" --tooltip "Print measure name" --contexts Measure +te macro set MyMacro -q tooltip -i "Updated tooltip" +te macro remove MyMacro +``` + #### macro init Create an empty macros file (`{"Actions":[]}`) at the configured path. Use this once when the resolved macros file does not yet exist. @@ -741,7 +832,7 @@ Deploy a semantic model to Power BI, Fabric, or Azure Analysis Services. - `--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. +- `-p, --profile ` - one-shot use of a saved @te-cli-auth profile. ```bash te deploy ./model -s my-workspace -d my-model --force --ci github @@ -752,18 +843,21 @@ 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. +> [!NOTE] +> When `--output-format json` is set, `te deploy`'s JSON payload always includes the resolved `server` and `database`, even when they were resolved from active connection or profile rather than passed explicitly. Pipelines can use these fields to confirm the deploy target without re-parsing the command line. `te deploy` and `te format` also exit non-zero on failure under `--output-format json`, matching their text-mode behavior - the JSON payload is the failure record, not a success signal. + ### refresh Trigger a data refresh on a deployed model. `te refresh` accepts: -- `--type ` - `full`, `dataonly`, `automatic`, `calculate`, `clearvalues`, `defragment`, `add` (default: `automatic`). +- `--type ` - `full`, `dataonly` (alias `data-only`, `data`), `automatic` (alias `auto`), `calculate` (alias `calc`), `clearvalues` (alias `clear`), `defragment` (alias `defrag`), `add` (default: `automatic`). - `--table ` - refresh specific table(s); repeatable. - `--partition ` - refresh specific partition(s). - `--apply-refresh-policy` - apply the incremental refresh policy to determine which partitions are refreshed. - `--effective-date ` - set the effective date used by the refresh policy. -- `--max-parallelism ` - set the maximum number of partitions to refresh in parallel. +- `--max-parallelism ` - set the maximum number of partitions to refresh in parallel. Wraps the refresh in a TMSL `sequence` command. - `--dry-run` - output the TMSL script without executing. - `--no-progress`, `--trace [path]`. @@ -781,7 +875,7 @@ Manage incremental refresh policies on tables. te incremental-refresh show ``` -Additional subcommands (`set`, `rm`, `apply`) are documented via `te incremental-refresh --help`. +Additional subcommands (`set`, `remove` (alias `rm`), `apply`) are documented via `te incremental-refresh --help`. ## Testing @@ -818,12 +912,14 @@ te test init --from-model --model ./my-model # Generate stubs from your measure 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 -te connect --clear # Clear the active connection (and any workspace mirror) +te connect # Show current active connection +te connect my-workspace my-model # Remote (positional) +te connect -s my-workspace -d my-model # Remote (named-flag form) +te connect ./model # Local +te connect --local # Power BI Desktop (Windows) +te connect --local my-report # Filter by report name (multiple PBI Desktop instances) +te connect --profile prod # Activate a saved profile +te connect --clear # Clear the active connection (and any workspace mirror) ``` #### Workspace mode (`-w` / `--workspace`) @@ -832,11 +928,11 @@ Pair a primary source with a secondary target so every subsequent `--save` mirro - `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). +- `--workspace-format ` - choose the on-disk format when mirroring to a folder/file: `tmdl`, `bim` (alias `tmsl`), or `database.json`. When omitted, the format is inferred from the workspace target path (e.g., `-w ./model.bim` infers BIM). - `--workspace-auth ` - auth method for a remote workspace target when the primary is local. Defaults to `--auth` if set, else `auto`. - `--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`. +Once active, `te set --save`, `te remove --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 @@ -853,21 +949,17 @@ Manage named connection profiles. See @te-cli-auth. ## Configuration -### config show / paths / init / set +### config list / paths / init / set -View and manage CLI configuration and TE3 path overrides. See @te-cli-config. +View and manage CLI configuration and TE3 path overrides. (`te config list` alias: `ls`.) See @te-cli-config. ```bash -te config show # Display all settings +te config list # Display all settings te config paths # Resolved TE3 file paths te config init # Create default config te config set autoFormat true ``` -### license - -`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 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. @@ -884,10 +976,19 @@ te migrate --output-format json # Machine-readable mapping Start a guided REPL session with a model-aware prompt. See @te-cli-interactive. +`te interactive` accepts: + +- `` - optional positional argument: start the session with a local model, `.bim` file, or `.SemanticModel` folder loaded. +- `--no-banner` - skip the welcome banner on startup. Useful when driving the REPL from scripts. +- `--echo` - echo each executed command to stdout before its output. Helpful when piping commands via stdin so the log shows what was run. +- `--batch` - non-interactive batch mode: read commands from stdin line by line, execute each, and exit on EOF. Automatically enabled when stdin is redirected. +- `--no-batch` - force interactive TTY mode even when stdin is redirected (mutually exclusive with `--batch`). + ```bash te interactive # Connect later te interactive ./model # Start with a local model te interactive -s MyWorkspace -d MyModel # Start with a remote model +printf "list Measures\nexit\n" | te interactive ./model # Pipe commands via stdin ``` 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. @@ -934,7 +1035,7 @@ te completion fish | Exit | Meaning | | -- | -- | | `0` | Success. | -| `1` | Generic failure (invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity ≥ error). For `te diff`: differences found. | +| `1` | Generic failure (invalid arguments, command failed, validation errors, auth failure, BPA gate failed at severity >= error). For `te diff`: differences found. | | `2` | `te diff` only: an error occurred while comparing, so the difference status is unknown. | For fine-grained control in CI pipelines, combine exit codes with `--ci ` annotations and `--trx` results files - see @te-cli-cicd. diff --git a/content/features/te-cli/te-cli-config.md b/content/features/te-cli/te-cli-config.md index 9a5db398e..8f6239a5c 100644 --- a/content/features/te-cli/te-cli-config.md +++ b/content/features/te-cli/te-cli-config.md @@ -18,13 +18,13 @@ applies_to: The Tabular Editor CLI reads optional configuration from a JSON file. Configuration controls three things: -- **File paths** — where the CLI reads macros, BPA rules, and (optionally) the TE3 Desktop executable, and where to write the query log. -- **Behavioral defaults** — BPA gates, auto-format, validation. -- **Saved connection profiles** — the list of named profiles you can switch between. +- **File paths** - where the CLI reads macros, BPA rules, and (optionally) the TE3 Desktop executable, and where to write the query log. +- **Behavioral defaults** - BPA gates, auto-format, validation. +- **Saved connection profiles** - the list of named profiles you can switch between. 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`). -Most users don't need to edit the config file directly - `te config show`, `te config set `, and `te profile set` cover the common operations. +Most users don't need to edit the config file directly - `te config list`, `te config set `, and `te profile set` cover the common operations. ## Config file location @@ -34,7 +34,7 @@ The following locations are checked in this 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. +`TE_CONFIG` is honored consistently by every config-file operation - `te config list`, `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: @@ -46,15 +46,15 @@ te config init --force # Overwrite existing config ## Viewing configuration ```bash -te config show # Display all settings -te config show --output-format json # Machine-readable +te config list # Display all settings +te config list --output-format json # Machine-readable te config paths # Show resolved macros and BPA rule paths ``` Use `te config paths` to see which files the CLI will actually use for macros and BPA rules. It's handy 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-format 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-format json` strips null fields by default, so consumers should parse it tolerantly. +> `te config paths` emits `null` fields explicitly in `--output-format 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 list --output-format json` strips null fields by default, so consumers should parse it tolerantly. ## Setting values @@ -78,7 +78,7 @@ The complete JSON config schema with all keys at their default values. Use this ```json { - "formatVersion": 1, + "formatVersion": 2, "macros": null, "autoFormat": false, "validateOnMutation": true, @@ -143,10 +143,10 @@ All BPA-related settings live under the `bpa` object and are addressed via dotte | Key | Default | Description | | -- | -- | -- | -| `autoFormat` | `false` | Run the DAX Formatter on modified expressions after `te add` / `te set` / `te mv` / `te macro run`. Uses the in-house formatter by default; opt into the SQL BI web service via `formatOptions.useSqlBiDaxFormatter`. | +| `autoFormat` | `false` | Run the DAX Formatter on modified expressions after `te add` / `te set` / `te move` / `te macro run`. Uses the in-house formatter by default; opt into the SQL BI web service via `formatOptions.useSqlBiDaxFormatter`. | | `validateOnMutation` | `true` | After a mutating command (`add`, `set`, `mv`, `replace --save`, `macro run`), check that every `Table[Column]` reference in the model still resolves. Catches dangling references introduced by renames or removals before they reach deploy. | | `bpa.onMutation` | `false` | Run a scoped BPA analysis after each mutating command (`set`, `add`, `mv`, `rm`, `macro run`). Only the affected table's objects are checked, not the whole model - useful for fast feedback during iterative edits. | -| `bpa.onDeploy` | `true` | Run the BPA gate before `te deploy` executes. The deploy is aborted if any rule fires at severity ≥ error. Bypass per-invocation with `--skip-bpa`, or auto-fix with `--fix-bpa`. | +| `bpa.onDeploy` | `true` | Run the BPA gate before `te deploy` executes. The deploy is aborted if any rule fires at severity >= error. Bypass per-invocation with `--skip-bpa`, or auto-fix with `--fix-bpa`. | | `bpa.onSave` | `true` | Run the BPA gate before `te save -o` writes to disk. Bypass per-invocation with `--skip-bpa` or `--force`. | | `bpa.builtInRules` | `true` | Include the curated built-in BPA rule set whenever the gate runs. Set to `false` to ignore built-ins entirely; the gate then runs only the rules configured via `bpa.rules` and any model-embedded rules. | | `bpa.disabledBuiltInRuleIds` | `null` | IDs of individual built-in rules to exclude from the gate. Mutated by `te bpa rules disable ` / `te bpa rules enable ` - prefer those over editing the array directly. | @@ -199,11 +199,11 @@ The BPA gate is the safety net that prevents a model with rule violations from b - `te deploy` runs the gate unless `--skip-bpa` is passed or `bpa.onDeploy` is `false`. - `te save` runs the gate unless `--skip-bpa` (or `--force`) is passed or `bpa.onSave` is `false`. -- `te add`, `te set`, `te mv`, `te macro run` run the gate only when `bpa.onMutation` is `true`. +- `te add`, `te set`, `te move`, `te macro run` run the gate only when `bpa.onMutation` is `true`. The gate loads BPA rules from `bpa.rules` and, 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: +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. @@ -218,13 +218,13 @@ 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. +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 remove` 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: +When you run a mutating command (`te add`, `te set`, `te move`, `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, or calculation items always fails the command. 2. **Schema validation** (`validateOnMutation`, default `true`) verifies that `Table[Column]` references in DAX still resolve, cross-checking metadata consistency. diff --git a/content/features/te-cli/te-cli-install.md b/content/features/te-cli/te-cli-install.md index 568023bad..0a858e352 100644 --- a/content/features/te-cli/te-cli-install.md +++ b/content/features/te-cli/te-cli-install.md @@ -131,7 +131,7 @@ te config set hidePreviewNotice true ## Shell completion -The CLI provides tab-completion scripts for **Bash**, **Zsh**, **PowerShell** and **Fish**. Pick the block that matches your shell — each one installs the completion persistently for new shell sessions. +The CLI provides tab-completion scripts for **Bash**, **Zsh**, **PowerShell** and **Fish**. Pick the block that matches your shell - each one installs the completion persistently for new shell sessions. ### Bash (macOS/Linux) diff --git a/content/features/te-cli/te-cli-interactive.md b/content/features/te-cli/te-cli-interactive.md index ef2fd7afd..85b456817 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-05-12 +updated: 2026-06-26 applies_to: products: - product: Tabular Editor 2 @@ -29,6 +29,13 @@ te interactive ./model # Start with a local model te interactive -s MyWorkspace -d MyModel # Start with a remote model ``` +`te interactive` accepts a few flags for tuning the session: + +- `--no-banner` - skip the welcome banner on startup. +- `--echo` - echo each executed command to stdout before its output. Useful for logging when driving the REPL from a script. +- `--batch` - non-interactive batch mode: read commands from stdin line by line, execute each, and exit on EOF. Automatically enabled when stdin is redirected. +- `--no-batch` - force interactive TTY mode even when stdin is redirected (mutually exclusive with `--batch`). + The session prints a welcome banner, shows the active model, and opens you at a model-aware prompt: ![Tabular Editor CLI interactive mode session](~/content/assets/images/features/cli/cli-interactive-mode.png) @@ -84,6 +91,64 @@ When interactive mode is active, commands that need missing input prompt for it To disable prompts for a single command inside the session, pass `--non-interactive`. +## Piped and redirected input + +Interactive mode also accepts piped or redirected stdin, so the same REPL can be driven from a script instead of typed by hand. Each line of input is run as a command, exactly as if you had entered it at the prompt, and the session exits when input is exhausted (or when it reaches an `exit` line). + +```bash +printf "ls\nexit\n" | te interactive ./model # bash / git-bash +te interactive ./model < script.te # redirected file +``` + +```bat +(echo ls & echo exit) | te interactive .\model :: Windows cmd.exe +``` + +Lines that start with `#` are treated as comments and skipped, so you can annotate a script file: + +``` +# script.te - inspect the model, then exit +ls tables +ls measures +exit +``` + +### Batch mode and exit codes + +When stdin is piped, `--batch` is the **default**: the session stops at the first command that fails and exits with a non-zero code, which makes a piped run safe to use as a build or CI step. Pass `--no-batch` to keep running the remaining lines even after a command fails. The process exit code is `0` for a clean run and non-zero when a command fails under batch mode. + +```bash +# Default when piped: stop at the first failing command, exit non-zero +printf "bpa run --fail-on error\ndeploy --force\nexit\n" | te interactive ./model + +# Run every line regardless of failures +printf "bpa run --fail-on error\ndeploy --force\nexit\n" | te interactive ./model --no-batch +``` + +### Readable transcripts + +`--echo` writes each input line to stdout ahead of its output, which is handy when capturing a transcript of a piped run. Comment lines are not echoed. + +```bash +printf "ls tables\nexit\n" | te interactive ./model --echo +``` + +### Options + +| Option | Description | +| -- | -- | +| `--no-banner` | Suppress the welcome banner. | +| `--echo` | Echo each input line to stdout (useful for piped transcripts). | +| `--batch` | Exit non-zero on the first failing command (default when stdin is piped). | +| `--no-batch` | Continue after errors even when stdin is piped. | + +### Welcome banner vs. preview notice + +Two separate messages can appear at the start of a session - don't conflate them: + +- The **welcome banner** is the interactive splash described under [Starting a session](#starting-a-session). It is suppressed with `--no-banner`. When stdin is piped, no welcome banner is emitted in the first place, so `--no-banner` has a visible effect only in a true interactive (TTY) session. +- The **preview-expiry notice** (`This is an early preview release ...`) is a different message. It is always written to **stderr** and is **not** affected by `--no-banner`. Suppress it with `te config set hidePreviewNotice true`. + ## 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. diff --git a/content/features/te-cli/te-cli-limitations.md b/content/features/te-cli/te-cli-limitations.md index ce83dd5d4..66f1e633d 100644 --- a/content/features/te-cli/te-cli-limitations.md +++ b/content/features/te-cli/te-cli-limitations.md @@ -42,9 +42,9 @@ The CLI runs C# scripts (`te script`) against the same `Model` object you use in | Limitation | Notes / Workaround | | -- | -- | -| **BPA rule sources must be HTTPS URLs or local file paths** | Only `https://` URLs and bare local file paths are accepted. `http://` is recognized but deliberately rejected at load time with a clear error - BPA rules are executable rule expressions, and fetching them over an unauthenticated channel would be a tampering risk. Other URL schemes (`file://`, `ftp://`, …) are not supported. Applies to both `te bpa run --rules` and the rule list configured via [`te config set`](xref:te-cli-commands#config-show--paths--init--set). | +| **BPA rule sources must be HTTPS URLs or local file paths** | Only `https://` URLs and bare local file paths are accepted. `http://` is recognized but deliberately rejected at load time with a clear error - BPA rules are executable rule expressions, and fetching them over an unauthenticated channel would be a tampering risk. Other URL schemes (`file://`, `ftp://`, …) are not supported. Applies to both `te bpa run --rules` and the rule list configured via [`te config set`](xref:te-cli-commands#config-list--paths--init--set). | | **Rule-URL validation runs at gate time, not on `te config set`** | A typo such as `http://` is accepted by `te config set` and only surfaces when BPA actually runs. After editing the configured rule sources, run `te bpa run` (or `te validate`) once to verify each URL loads. | -| **`--rules` does not suppress built-in rules** | When `te bpa run --rules ` is passed, the supplied rules replace the entries in [`bpa.rules`](xref:te-cli-commands#config-show--paths--init--set) and `TE_BPA_RULES` for that invocation, but the built-in defaults still load alongside. To run only the explicit rule file, also pass `--no-defaults`. | +| **`--rules` does not suppress built-in rules** | When `te bpa run --rules ` is passed, the supplied rules replace the entries in [`bpa.rules`](xref:te-cli-commands#config-list--paths--init--set) and `TE_BPA_RULES` for that invocation, but the built-in defaults still load alongside. To run only the explicit rule file, also pass `--no-defaults`. | | **No per-invocation flag to skip `bpa.rules` config** | Once `bpa.rules` is configured, every `te bpa run` loads those rules in addition to the built-ins. There is currently no flag to skip the configured rule files for a single run. Workaround: pass `--rules ` explicitly - the flag fully replaces `bpa.rules` and `TE_BPA_RULES` for that invocation. | ## Validation @@ -57,7 +57,7 @@ The CLI runs C# scripts (`te script`) against the same `Model` object you use in | Limitation | Notes / Workaround | | -- | -- | -| **`--serialization` cannot combine a serialization with a PBIP container** | The `--serialization` option on [`te save`](xref:te-cli-commands#save) treats `bim`, `tmdl`, `te-folder`, and `pbip` as mutually exclusive, so you cannot currently produce a PBIP container around a TMSL-serialized (`.bim`) model. Save TMDL inside PBIP, or save `.bim` outside a PBIP wrapper. | +| **`--serialization` cannot combine a serialization with a PBIP container** | The `--serialization` option on [`te save`](xref:te-cli-commands#save) treats `bim`, `tmdl`, `database.json`, and `pbip` as mutually exclusive, so you cannot currently produce a PBIP container around a TMSL-serialized (`.bim`) model. Save TMDL inside PBIP, or save `.bim` outside a PBIP wrapper. | ## Authentication diff --git a/content/features/te-cli/te-cli-migrate.md b/content/features/te-cli/te-cli-migrate.md index aeaf127a5..f3962d81b 100644 --- a/content/features/te-cli/te-cli-migrate.md +++ b/content/features/te-cli/te-cli-migrate.md @@ -57,15 +57,15 @@ A non-exhaustive summary of the most commonly used flags. Run `te migrate` for t | 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. | +| `server`, `database` | `te connect ` or `te deploy -s -d ` | Server is no longer a global positional; `te deploy` takes only `` positionally, with server and database as named flags. | | `-L` / `-LOCAL` | `te connect --local` | Windows only. | | `-S` / `-SCRIPT` | `te script -S ` or `-e "code"` | Supports multiple scripts, inline code, and stdin. Note: uppercase `-S` - lowercase `-s` is the global `--server` option. | | `-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 --serialization bim` | | -| `-F` / `-FOLDER` | `te save -o --serialization te-folder` | After `-D`, TE2's `-F` means `-FULL` - see `--deploy-full`. | +| `-F` / `-FOLDER` | `te save -o --serialization database.json` | After `-D`, TE2's `-F` means `-FULL` - see `--deploy-full`. | | `-TMDL` | `te save -o --serialization tmdl` | TMDL is the default save format. | -| `-D` / `-DEPLOY` | `te deploy ` | Separate command with named options. | +| `-D` / `-DEPLOY` | `te deploy -s -d ` | Separate command with named options; only `` is positional. | | `-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` | | diff --git a/content/features/te-cli/te-cli.md b/content/features/te-cli/te-cli.md index 5c091878d..3ae87532d 100644 --- a/content/features/te-cli/te-cli.md +++ b/content/features/te-cli/te-cli.md @@ -26,9 +26,9 @@ Unlike the Windows-only `TabularEditor.exe` command-line options (TE2) - which w Three design pillars run through every command: -- **Structured output** — JSON, CSV, TMDL, TMSL alongside default human-readable text. -- **Non-interactive mode** — a global `--non-interactive` flag that disables prompts and fails fast. -- **Clear errors** — written to stderr with predictable exit codes. +- **Structured output** - JSON, CSV, TMDL, TMSL alongside default human-readable text. +- **Non-interactive mode** - a global `--non-interactive` flag that disables prompts and fails fast. +- **Clear errors** - written to stderr with predictable exit codes. Together they make the same binary work well for three very different audiences: @@ -48,14 +48,14 @@ See @te-cli-commands for a full command reference with syntax, options, and exam | Family | What it does | Example commands | | -- | -- | -- | | [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) | +| [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 remove`](xref:te-cli-commands#remove), [`te move`](xref:te-cli-commands#move) | +| [Inspection](xref:te-cli-commands#inspection) | List objects, search, diff, dependency analysis | [`te list`](xref:te-cli-commands#list), [`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 & Authentication](xref:te-cli-commands#connection-and-authentication) | 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) | +| [Configuration](xref:te-cli-commands#configuration) | Settings and licensing | [`te config`](xref:te-cli-commands#config-list--paths--init--set) | | [Shell](xref:te-cli-commands#shell) | Interactive mode, session state, shell completions | [`te interactive`](xref:te-cli-commands#interactive), [`te session`](xref:te-cli-commands#session), [`te completion`](xref:te-cli-commands#completion) | ## Getting started @@ -69,10 +69,10 @@ A first look at a live model takes two commands: ```bash te auth login -te ls -s MyWorkspace -d MyModel +te list -s MyWorkspace -d MyModel ``` -![Tabular Editor CLI te ls example output](~/content/assets/images/features/cli/cli-command-ls.png) +![Tabular Editor CLI te list example output](~/content/assets/images/features/cli/cli-command-ls.png) ## Preview notice