Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions skills/te-cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

All notable changes to the `te-cli` skill are documented in this file.

## [0.3.0] - 2026-07-02

Aligns the skill with CLI 0.6.0.

### Changed

- Rewrote every command example to use long-form canonical verbs (`te list`, `te remove`, `te move`, `te config list`), with a short callout that Unix aliases (`ls`, `rm`, `mv`) still work everywhere. `te move` also accepts `rename`. `te add` has no short alias.
- Replaced every `--serialization te-folder` occurrence with `database.json` (BREAKING CLI rename in 0.6.0). The mirror on `te connect --workspace-format` and the TE2 migration table (`-F <dir>`) both track the new spelling.
- Removed the "known gap" language for `te list Relationships`: the CLI now enumerates relationships correctly, so SKILL.md and `references/command-reference.md` list `Relationships` as an enumerable container next to `Tables`, `Measures`, etc. The gotcha entry now covers the residual issue (system-assigned relationship names) rather than the wiring gap.
- Dropped the "`--source-type m` on models with a provider data source" pre-validation error from `references/workflows.md`; the CLI now accepts mixed-partition models to match TE3 desktop.

### Added

- `te query "<dax>"` positional-DAX shorthand documented in the quickstart and `references/command-reference.md`; explicit `-q` still wins when both are supplied.
- `te macro set` now accepts repeated `-q <property> -i <value>` pairs in one call, with a worked example in `references/command-reference.md`.
- `te interactive` batch mode (redirected stdin) and its new flags (`--no-banner`, `--echo`, `--batch` / `--no-batch`) added to `references/command-reference.md`, with a batch-mode example block.
- New `launchInteractiveMode` config key (`Auto` / `Never` / `Always`) documented in `references/config-cicd-env.md`.
- `--serialization tmsl` documented as an alias for `bim` (canonical) on `te save`, `te init`, and `te connect --workspace-format`.
- Note that `te bpa run` text output now includes a `Rule ID` column, so IDs can be copied straight into `--fix --rule <id>`.
- Note that `te vertipaq` surfaces a clear error on unknown table/column filters (with up to 10 candidates), and its output is pipe-safe (`te vertipaq > report.txt`, `te vertipaq | less`).

[0.3.0]: https://github.com/TabularEditor/CLI/releases/tag/skill-v0.3.0

## [0.2.0] - 2026-06-08

### Changed
Expand Down
34 changes: 19 additions & 15 deletions skills/te-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: te-cli
version: 0.2.0
version: 0.3.0
description: Expert guidance for the cross-platform Tabular Editor CLI (the `te` binary, currently in preview) that manages Power BI / Analysis Services semantic models from the terminal on macOS, Linux, and Windows. Use when the user mentions the `te` CLI or "Tabular Editor CLI" (not the "2"), or runs a `te <command>` to scaffold, inspect, edit, validate, run BPA on, query, deploy, refresh, test, or migrate a semantic model. Not for the legacy Windows-only `TabularEditor.exe` (TE2).
---

Expand Down Expand Up @@ -32,12 +32,16 @@ The `te` CLI is a single self-contained binary that loads, edits, validates, dep
- First use in a session: run `te --version` and `te auth status`. If not authenticated, ask the user to run `te auth login`.
- Run `te --help` and `te <command> --help` the first time composing a command; flags are still evolving during preview.
- `te connect` state is per-shell-session and does NOT survive across separate Bash tool calls (each call is a fresh shell). Pass `-m <model>` (and `-s`/`-d` for remote) on every command, or set `TE_SESSION=<name>` before the first call to share state.
- MPartition path asymmetry: `te add` for an M partition uses `<Table>/<Partition>`, but every other command (`te rm`, `te get`, `te ls`, `te mv`, `te set`) uses `<Table>/Partitions/<Partition>`.
- Mutations stage in memory by default. `te set`, `te add`, `te rm`, `te mv`, `te replace`, `te format`, `te script`, `te macro run`, `te incremental-refresh set/remove` need `--save` to persist (unless `interactiveEditMode` is set to `save`).
- MPartition path asymmetry: `te add` for an M partition uses `<Table>/<Partition>`, but every other command (`te remove`, `te get`, `te list`, `te move`, `te set`) uses `<Table>/Partitions/<Partition>`.
- Mutations stage in memory by default. `te set`, `te add`, `te remove`, `te move`, `te replace`, `te format`, `te script`, `te macro run`, `te incremental-refresh set/remove` need `--save` to persist (unless `interactiveEditMode` is set to `save`).
- The BPA gate is ON by default for `te deploy` and `te save`. Bypass deliberately: `--skip-bpa`, `--fix-bpa`, or `bpa.onDeploy` / `bpa.onSave` config (keys are nested under `bpa.`, not flat).
- In CI: pass `--non-interactive` and `--force`. `te deploy` prompts with `n` as the safe default and hangs pipelines without `--force`.
- Never put secrets on the command line (visible in `ps` and shell history). Use `--auth env` with `AZURE_CLIENT_ID`/`AZURE_CLIENT_SECRET`/`AZURE_TENANT_ID`, stdin (`-`), or `--auth managed-identity`.
- Avoid destructive operations without explicit direction: `te rm`, `te mv`, `te deploy --create-only`, `te save --force`, `te connect --clear`. If a command is blocked by permissions, stop and ask.
- Avoid destructive operations without explicit direction: `te remove`, `te move`, `te deploy --create-only`, `te save --force`, `te connect --clear`. If a command is blocked by permissions, stop and ask.

## Verb naming (canonical long-form + Unix aliases)

Long-form verbs are canonical: `te list`, `te remove`, `te move` at the root, and `list`/`remove` in subgroups (`te macro`, `te bpa rules`, `te profile`, `te session`, `te test`, `te incremental-refresh`). Short Unix-style aliases work everywhere: `ls`, `rm`, `mv`. `te move` also accepts `rename`. `te config list` is the canonical name (previously `te config show`). `te add` has no short alias. This skill uses the long forms throughout; the aliases still work if you prefer to type them.

## Staging model (`--save` / `--stage` / `--revert`)

Expand All @@ -57,13 +61,13 @@ Inside `te interactive`, `--save`, `--stage`, and `--revert` are available per c
te --version && te auth status # 0. check install + auth
te auth login # 1. authenticate (browser); cached
te init ./my-model # 2. scaffold (PowerBI mode, TMDL, compat 1702)
te load ./model # 3. load + summary; then `te ls`, `te ls Sales`
te load ./model # 3. load + summary; then `te list`, `te list Sales`
te find "Revenue" --in names -m ./model # 4. search (names | expressions | descriptions | all)
te get Sales/Revenue -q expression -m ./model # 5. read a measure's DAX
te bpa run --fail-on error --ci github -m ./model # 6. BPA gate
te format --save -m ./model # 7. format all DAX
te query -q "EVALUATE TOPN(5, 'Sales')" -s ws -d model # 8. query
te save -o ./out --serialization tmdl -m ./model # 9. save / convert (tmdl|bim|pbip|te-folder)
te query "EVALUATE TOPN(5, 'Sales')" -s ws -d model # 8. query (positional or -q)
te save -o ./out --serialization tmdl -m ./model # 9. save / convert (tmdl|bim|pbip|database.json)
te deploy ./model -s ws -d model --force --ci github # 10. deploy
te refresh --type full -s ws -d model # 11. refresh
```
Expand All @@ -74,13 +78,13 @@ te refresh --type full -s ws -d model # 11. refresh

The highest-frequency tasks in their most concise form. Full flags are in `references/command-reference.md`; flags are still moving in preview, so confirm with `te <command> --help`.

1. **Summarize a model (most concise)**: `te load ./model` prints a model summary. For a structural inventory, `te ls` (tables), `te ls Measures` (every measure across the model). Relationships do not list via `te ls` (a known gap, see `references/gotchas.md`); enumerate them with `te query -q "EVALUATE INFO.VIEW.RELATIONSHIPS()"`. Add `--output-format json` for a machine-readable dump.
2. **Search the model (fastest)**: `te find "<text>" --in names --paths-only -m ./model`. Scope `--in` to `names`, `expressions`, `descriptions`, `displayFolders`, ...; `--in expressions` walks every DAX and M expression. `--paths-only` is the fast, pipeable form. Structural lookups use wildcards (`te ls "Sales/*Amount"`). Relationships are not `te ls`-enumerable (known gap); list them with `te query -q "EVALUATE INFO.VIEW.RELATIONSHIPS()"`.
1. **Summarize a model (most concise)**: `te load ./model` prints a model summary. For a structural inventory, `te list` (tables), `te list Measures` (every measure across the model), `te list Relationships` (all relationships). Add `--output-format json` for a machine-readable dump.
2. **Search the model (fastest)**: `te find "<text>" --in names --paths-only -m ./model`. Scope `--in` to `names`, `expressions`, `descriptions`, `displayFolders`, ...; `--in expressions` walks every DAX and M expression. `--paths-only` is the fast, pipeable form. Structural lookups use wildcards (`te list "Sales/*Amount"`). Relationships are enumerated with `te list Relationships` (or DAX `EVALUATE INFO.VIEW.RELATIONSHIPS()` for the friendly view with cross-filter direction and active flag).
3. **Query the model**:
- Inline DAX: `te query -q "EVALUATE TOPN(10, Sales)" -m ./model`
- Positional DAX: `te query "EVALUATE TOPN(10, Sales)" -m ./model` (or `-q "<dax>"`; explicit `-q` still wins)
- From a `.dax` file: `te query -f query.dax -m ./model`
- Save results (format picked by extension): `--output-file out.csv` (csv/tsv/json/dax); machine-readable stdout: `--output-format json`.
4. **Make a change** (stages in memory; `--save` persists): `te set Sales/Revenue -q expression -i "SUM(Sales[Amount])" --save`. Also `te add`, `te rm`, `te mv`. Read the current value first with `te get Sales/Revenue -q expression`.
4. **Make a change** (stages in memory; `--save` persists): `te set Sales/Revenue -q expression -i "SUM(Sales[Amount])" --save`. Also `te add`, `te remove`, `te move`. Read the current value first with `te get Sales/Revenue -q expression`.
5. **Make bulk changes**:
- Text find/replace across the whole model: `te replace "Old" "New" --in expressions --save` (previews unless `--save`).
- Arbitrary bulk logic in one pass (the model loads once, avoiding ~1-2s per-call startup): `te script -S bulk.csx --save`, or inline `echo '<C# foreach over Model.AllMeasures>' | te script -e - --save`. Predefined macros: `te macro run "<name>" --on "Sales/A,Sales/B" --save`.
Expand Down Expand Up @@ -114,7 +118,7 @@ Driving the CLI correctly is not the same as building a good model. After `te ad
| `summarizeBy` = `none` on key/ID columns | stops Power BI silently summing keys into meaningless totals | `te set Sales/ProductKey -q summarizeBy -i none --save` |
| Hide foreign-key and surrogate-key columns | keys serve relationships, not visuals; keeps the field list clean | `te set Sales/ProductKey -q isHidden -i true --save` |
| Mark the date table | unlocks reliable time intelligence | `te set Date -q dataCategory -i Time --save` |
| Single cross-filter direction by default | avoids ambiguous filter paths and double counting | list with `te query -q "EVALUATE INFO.VIEW.RELATIONSHIPS()"` (`te ls` cannot enumerate relationships; see gotchas), read one with `te get Relationships/<name>` (the `->` shorthand is for `te add` only); enable bidirectional only for a deliberate bridge |
| Single cross-filter direction by default | avoids ambiguous filter paths and double counting | list with `te list Relationships` (or DAX `EVALUATE INFO.VIEW.RELATIONSHIPS()` for the friendly view), read one with `te get Relationships/<name>` (the `->` shorthand is for `te add` only); enable bidirectional only for a deliberate bridge |
| Format string on every measure | unformatted measures render raw floats | `te set "_Measures/Revenue" -q formatString -i "#,0.00" --save` |
| Display folder + description on measures | a flat field pane is unusable past a few dozen measures; descriptions feed tooltips and Copilot | `te set "_Measures/Revenue" -q displayFolder -i "Revenue" --save` |
| Minimal correct data types; integer surrogate keys | high-cardinality and oversized types bloat VertiPaq | `te set Sales/CustomerKey -q dataType -i int64 --save` |
Expand All @@ -129,8 +133,8 @@ Full rationale, citations, and worked workflows (RLS roles, calculation groups,
Ten command families. Full flags and examples in `references/command-reference.md`.

- Model I/O: `te load`, `te save`, `te open`, `te init`
- Editing: `te set`, `te add`, `te rm`, `te mv`, `te replace`
- Inspection: `te ls`, `te get`, `te find`, `te diff`, `te deps`
- Editing: `te set`, `te add`, `te remove`, `te move`, `te replace`
- Inspection: `te list`, `te get`, `te find`, `te diff`, `te deps`
- Analysis & quality: `te validate`, `te bpa run`, `te vertipaq`, `te format`
- Execution: `te query`, `te script`, `te macro`
- Deploy & refresh: `te deploy`, `te refresh`, `te incremental-refresh`
Expand All @@ -155,7 +159,7 @@ For build scripts that issue many `te` calls, set `te config set bpa.onSave fals

`te` owns the semantic model. Two sibling CLIs own the layers around it, and the highest-value workflows cross the boundary:

- `pbir` (the Power BI report layer): renaming or moving a model object leaves the report bound to the old `Table.Field`. Rename in the model (`te mv`, then `te replace --in expressions --save`), then repair the report bindings (`pbir fields replace`, `pbir validate --fields`). See `references/pbir-cli-tandem.md`.
- `pbir` (the Power BI report layer): renaming or moving a model object leaves the report bound to the old `Table.Field`. Rename in the model (`te move`, then `te replace --in expressions --save`), then repair the report bindings (`pbir fields replace`, `pbir validate --fields`). See `references/pbir-cli-tandem.md`.
- `fab` (the Fabric / Power BI service): export a model from a workspace, edit and gate it locally with `te`, then deploy over XMLA (`te deploy`) or import it back (`fab import`). See `references/fabric-cli-tandem.md`.

Gate any cross-tool refactor with `te validate` before touching the report or the service, and remember every `te` mutation stages in memory until `--save`.
Expand Down
Loading