Connect¶
Commands for working with connections and deployed models. The connection model itself — sessions, profiles, workspace mode — is explained in Connections & sessions.
connect — set the active connection¶
No arguments shows the current connection and the
session that holds it. For a Power BI
Desktop session it shows the report name, and flags the session as
(not running) — with the last-known report — once that Desktop window has
been closed. The first argument can be a workspace name, an endpoint, or a
local model path.
| Option | Description |
|---|---|
--local |
Attach to a Power BI Desktop instance running on this machine (Windows only). The instance's database (a GUID) is looked up and saved automatically. |
--list |
List without connecting or changing the active connection. With a server (tx connect <workspace> --list): the semantic models on that workspace or endpoint, with compatibility level and last update. With --local: running Desktop instances (report name, endpoint, database). Works without a TTY; use --output-format json for scripts and agents. |
--remote |
Pick a workspace and model interactively from your tenant (requires a TTY; sign in first with tx auth login). |
-p, --profile <name> |
Connect through a saved profile. |
--clear |
Forget the active connection. Add --all to forget it in every session (every repository, worktree, and TOMIX_SESSION); that asks for confirmation, so pass --yes in scripts. |
-w, --workspace [target] |
Enable workspace mode: mirror saves between the primary source and a secondary target. No value = pick interactively. |
--workspace-format <fmt> |
How a local workspace is stored on disk (tmdl or bim); detected from the path when omitted. |
--workspace-auth <auth> |
How to authenticate the remote side of workspace mode. |
--overwrite |
With -w, delete the workspace folder's contents before exporting the model into it, and overwrite an existing workspace database without asking. |
tx connect # show current
tx connect --remote
tx connect MyWorkspace Sales
tx connect ./model.tmdl
tx connect --local # Power BI Desktop (Windows only)
tx connect MyWorkspace --list # models on a workspace, no connect
tx connect --local --list # running Desktop instances, no connect
tx connect localhost:56164 # a specific Desktop instance from the list
tx connect ./model.tmdl -w MyWorkspace Sales
tx connect --clear --all # forget the connection everywhere
A workspace that hosts more than one model cannot be opened without naming one:
commands such as tx ls -s MyWorkspace fail with TOMIX_DATABASE_REQUIRED. List
the models first, then pass one with -d:
With --output-format json the listing is
{"server": "<endpoint>", "models": [{"name", "compatibilityLevel", "lastUpdate"}]}
inside the standard envelope; compatibilityLevel and lastUpdate are null when the
server does not report them.
deploy — deploy to a workspace¶
Runs the BPA gate before deploying. The gate blocks only on findings at or above the
severity threshold: error-severity by default, or warnings too with --bpa-fail-on warning.
A rule that cannot be evaluated is itself an error-severity finding — a broken rule
expression blocks the deploy (named in the message) instead of silently skipping the rule.
The built-in statistics rules are in the default-off vertipaq preset; the gate adds it
to standard when the model has Vertipaq_* annotations, so a model annotated with
tx vertipaq --annotate --save is checked for referential-integrity and size problems.
When a rule from bpa.rules, TOMIX_BPA_RULES, or --bpa-rules needs VertiPaq
statistics the model doesn't have, it is not checked. The deploy
still proceeds, with a TOMIX_BPA_VERTIPAQ_STATS_MISSING warning that names them and
says how to collect the statistics: tx vertipaq --annotate --save on a deployed model,
or on a local model connected to one in workspace mode.
Besides the built-in standard ruleset, the gate loads the rule files that the bpa.rules
config key and the TOMIX_BPA_RULES environment variable name, then --bpa-rules; a later
source overrides an earlier one for the same rule ID (see
rule sources). Set TOMIX_BPA_RULES in a pipeline to gate every
deploy on the team's rules. The gate honors bpa rules ignore --user: it skips any rule you
ignore locally when that rule is among the gate's loaded rules. bpa run also loads your
config-dir bpa-rules.json and the model's rules, so the commands may report different findings.
Without -s/--server, the target comes from the active connection: a remote connection
deploys to itself, and a local connection with a workspace-mode mirror deploys to the
mirror.
deploy previews first. It shows what the deploy would change on the target (+ = added
to the target, - = removed from it), then asks before deploying. The preview compares the
target against the exact model this deploy would leave behind, so anything
granular deployment preserves is not reported as a change, and a
target that does not exist yet is reported as "will be created". Where it cannot prompt
(--non-interactive, --quiet, JSON output, or redirected input), it stops after the
preview and exits 3. Pass --yes to deploy without the preview. --xmla only writes a
script, so it neither previews nor asks.
| Option | Description |
|---|---|
--xmla <file> |
Write the deployment as a TMSL script to a file instead of deploying (- for stdout). |
--create-only |
Create the target model only if it does not exist; fail when it does. |
--skip-bpa / --fix-bpa |
Skip the BPA gate, or apply rule fixes before deploying. |
--bpa-rules <file> |
Additional BPA rule files for this deploy, alongside the built-in ruleset, bpa.rules, and TOMIX_BPA_RULES; they override those for the same rule ID. |
--bpa-fail-on <error\|warning> |
Severity threshold for the BPA gate: error (default) or warning. Applies before the deploy and again after --fix-bpa fixes. Rules that cannot be evaluated count as error-severity findings. |
-p, --profile <name> |
Use a saved remote profile for this deploy only. List profiles with tx profile list; create one with tx profile set <name> -s <workspace> -d <database>. |
--rollback-on-error |
Check the deployed model before it is committed, and roll the deploy back when an object is in an error state. See Rolling back a broken deploy. |
--ci <github\|vsts> |
Print CI annotations to stderr for post-deploy errors and warnings. |
After a deploy runs, deploy re-reads the deployed model and checks the state the server
reports for each object — the server accepts a model whose DAX does not resolve, so
"deployed" alone is not proof it works. Measures, columns, partitions, calculation items,
format-string and detail-rows expressions, hierarchies, relationships, RLS table
permissions, and functions are checked:
| Server state | Severity | Effect |
|---|---|---|
| Semantic, evaluation, or dependency error | error | Listed; TOMIX_DEPLOY_VALIDATION_FAILED, exit 1. The model is deployed. |
| Incomplete | warning | Listed; TOMIX_DEPLOY_VALIDATION_WARNINGS, exit 0. |
| No data, calculation needed | info | Counted as unprocessed — normal after a metadata deploy; tx refresh processes them. Exit 0. |
If the deployed model cannot be re-read, the deploy still succeeds with a
TOMIX_DEPLOY_VALIDATION_UNAVAILABLE warning. With --ci, errors and warnings become CI
annotations. JSON output adds a validation object to data (omitted on previews and
--xmla):
"validation": {
"issues": [
{"severity": "Error", "objectType": "Measure", "objectName": "Sales[Total]",
"state": "SemanticError", "message": "..."}
],
"errors": 1, "warnings": 0, "unprocessed": 0
}
The preview diff ignores engine-derived calculated-table column data types, including type differences when a column exists on both the processed target and the planned model. Other column property changes remain visible.
tx deploy ./model.tmdl # preview, then confirm
tx deploy ./model.tmdl --profile prod --yes # deploy without the preview (CI)
tx deploy --server MyWorkspace --database Sales
tx deploy ./model.bim --xmla deploy.xmla
tx deploy ./model.tmdl --bpa-fail-on warning
Rolling back a broken deploy¶
Without --rollback-on-error, the check above runs after the deploy has committed, so a
model with errors is already live on the target when deploy reports it. With
--rollback-on-error, the check runs before the change is kept, and a deploy with an error
never reaches the target:
- Existing model. The deploy runs inside a server transaction. It applies the same merged model as an ordinary deploy, including everything granular deployment preserves. While the transaction is open, the server already reports the state of the uncommitted objects. If an object is in an error state, the transaction rolls back and the target keeps its previous definition and data. Otherwise it commits.
- New model. The server cannot create a database inside a transaction. The deploy creates the model and checks it, and if an object is in an error state it deletes the model again.
A rolled-back deploy fails with TOMIX_DEPLOY_ROLLED_BACK (exit 1), lists the broken
objects, and reports "status": "rolled-back" in JSON. A check that cannot read the model
also rolls back, because nothing proves the model works. Warnings (incomplete objects) and
unprocessed objects do not roll back. The flag cannot change a model's compatibility level,
because that change commits on its own; deploy once without the flag to upgrade the level.
--rollback-on-error cannot be combined with --xmla.
Granular deployment¶
When the target model already exists, deploy preserves everything the target owns by
default: partitions (including processed incremental-refresh data), data source connection
strings, shared expressions (M parameters), roles, and role members. Only the model
structure — tables, columns, measures, relationships — is overwritten. Each aspect can be
opted into deployment individually:
| Option | Description |
|---|---|
--deploy-connections |
Overwrite the target's data sources. Default keeps the target's connection strings and bound credentials. |
--deploy-partitions |
Overwrite the target's table partitions. Default keeps the target's partitions and their processed data. Calculated tables and calculation groups are exempt: their partitions are model structure (a DAX expression), so they always deploy from the source. |
--deploy-policy-partitions |
With --deploy-partitions: also overwrite incremental-refresh policy partitions. Default keeps them even when other partitions deploy, so processed history is never discarded by accident. |
--deploy-shared-expressions |
Overwrite the target's shared expressions (M parameters). Default keeps the target's values; expressions new in the source always deploy. |
--deploy-roles |
Overwrite the target's security roles. Default keeps the target's roles untouched. |
--deploy-role-members |
With --deploy-roles: also overwrite role members. Default keeps the target's membership even when role definitions deploy. |
--deploy-full |
Overwrite everything from the source, including incremental-refresh partitions. Cannot be combined with the other --deploy-* flags. |
Preservation only applies to an existing target; the first deploy of a model always ships
the full source. --xmla reads the target when any aspect is preserved so the generated
script matches what a real deploy would execute — use --deploy-full to generate a script
offline. Generated scripts never contain credentials: only a direct deploy carries
restricted connection-string information. On targets with dataSource objects (Azure AS,
SSAS — Power BI and Fabric models keep connections in M instead), this means an --xmla
script is not equivalent to a direct deploy: createOrReplace replaces each data
source with the credential-stripped copy in the script, so executing it disconnects those
data sources until credentials are re-entered on the server. Prefer a direct deploy when
data sources are in play; treat --xmla output as a preview or an
audit artifact there, not a deployment vehicle.
tx deploy ./model.tmdl # promote structure, keep target data and config
tx deploy ./model.tmdl --deploy-roles # also push RLS definitions, keep members
tx deploy ./model.tmdl --deploy-partitions # push partitions, keep incremental-refresh data
tx deploy ./model.tmdl --deploy-full # overwrite everything (first-deploy semantics)
The preview reflects preservation
The preview reads the target once and compares it against the model this deploy would
actually leave behind, merged with the same rules a real deploy uses. Aspects the flags
preserve — connection strings, M parameter values, role members, incremental-refresh
partitions — are therefore absent from the diff, and changing a --deploy-* flag changes
what the preview reports.
With default flags or --deploy-roles alone, a members-only source edit can show "No changes"
in the preview because an existing target's role members are preserved. A real deploy also
leaves those members unchanged; use --deploy-roles --deploy-role-members (or --deploy-full)
to preview and deploy member changes.
When the target database does not exist, there is nothing to compare against: the preview reports that the deploy creates it with the full source model.
--xmla still shows the raw payload rather than a diff, and remains the way to inspect
the exact TMSL that would be sent:
refresh — trigger a data refresh¶
| Option | Description |
|---|---|
--refresh-type <type> |
full, dataonly, automatic (default), calculate, clearvalues, defragment, add. Named --refresh-type (not --type): --type means an object kind on every other command. |
--table <name> |
Refresh specific table(s). Repeatable. |
--partition <Table.Partition> |
Refresh specific partition(s). Repeatable. |
--apply-refresh-policy [true\|false] / --skip-refresh-policy |
Let an incremental refresh policy choose the partitions (default: true); --skip-refresh-policy is shorthand for --apply-refresh-policy false. |
--policy-only |
Apply one table's deployed policy without loading data. Requires exactly one --table; may remove expired partitions. |
--effective-date <yyyy-MM-dd> |
Evaluate refresh policies as if today were this date. |
--max-parallelism <n> |
Maximum parallel refresh operations. |
--no-progress |
Turn off live progress tracking (useful in CI and when piping). |
--trace [path] |
Write raw XMLA trace events (stderr, or a log file). |
tx refresh --refresh-type full
tx refresh --table Sales --table Customers
tx refresh --model "Sales.SemanticModel" --table Sales # the PBIP open in Power BI Desktop
Files cannot be refreshed, so the target is a deployed model: the connection's server, or its
workspace-mode secondary. When the model is a PBIP's files (the .pbip, its .SemanticModel
folder, or anything in it) and no remote target is set, refresh runs in the Power BI Desktop
that has that PBIP open, and says so. Save in Desktop to keep the data. Desktop is found from the
file it was started with, so a project opened from Desktop's File menu is not matched: pass
--server localhost:<port> (tx connect --local --list shows it) instead.
While it runs, a live panel shows the elapsed time, how many tables are done and in progress,
and the rows loaded so far, then one line per in-progress table — oldest first, capped at six —
with its current step (querying, reading, compressing, hierarchies, calculated columns), the
partition for multi-partition tables, its rows, and how long it has been running. Once no table is
in progress it shows the model-level step (relationships, calculation script, commit). The summary lists each table with Rows, Query (source query), Read, Process
(post-load hierarchies and calculated columns), and Total, with a sub-row per partition when a
table has several, followed by a phase table (data load, hierarchies, calculated columns,
relationships, calculation script, commit) in wall-clock time. With --output-format json the same
detail is in tables[].processMs, tables[].partitions, and phases; the CSV columns are
unchanged. Power BI / Fabric delivers the trace a few seconds behind the refresh, so the summary
can appear a little after the refresh itself finishes; the reported duration is the refresh's own.
Routine refreshes run straight away. The partition-risky variants preview first:
--refresh-type clearvalues (wipes partition data), --skip-refresh-policy /
--apply-refresh-policy false (refreshes all historical partitions), --policy-only, and
--effective-date (shifts policy window boundaries). They print the TMSL the refresh would
send (a validated operation summary for --policy-only), then ask before refreshing, on the
same connection. Where they cannot prompt (--non-interactive, --quiet, JSON output, or
redirected input), they stop after the preview and exit 3. Pass --yes to run them
without the preview.
Apply a saved policy with data loading, or bootstrap empty partitions:
tx refresh --table Sales --apply-refresh-policy true -s MyWorkspace -d MyModel
tx refresh --table Sales --policy-only -s MyWorkspace -d MyModel # preview, then confirm
tx refresh --table Sales --policy-only -s MyWorkspace -d MyModel --yes
--policy-only uses the deployed policy; it does not deploy local edits. It accepts
--effective-date and positive --max-parallelism. It cannot be combined with
--partition, an explicit --refresh-type, --trace, or disabling policy application.
Its preview verifies the target table and policy without applying it; exact partition
changes are determined by the server during execution. JSON execution results include
policyApplication (operations, date, and refreshed: false); previews include
policyPreview. Ordinary refresh output remains unchanged.
After an empty policy-only bootstrap, a normal policy refresh loads the incremental window; historical partitions can remain empty. To backfill all existing partition ranges without moving the policy window, use:
save — export a model¶
| Option | Description |
|---|---|
-o, --output-file <path> |
Where to write. Omit to save back to the source. |
--serialization <tmdl\|bim> |
Output format (defaults to the loaded model's). |
--supporting-files |
Write a {modelName}.SemanticModel/ folder (with .platform and definition.pbism) around the output. |
--fix-bpa / --bpa-rules <file> |
Apply BPA rule fixes before saving, optionally with specific rule files. |
--overwrite |
Replace an existing output file or directory. |
--no-sync |
Skip the workspace mirror when workspace mode is active. |
-f, --force |
In a live session (tx interactive, tx ui), write over changes made to the model's files outside it, instead of failing with TOMIX_SESSION_STALE. |
tx save -s MyWorkspace -d Sales -o ./sales.tmdl # download a deployed model
tx save ./model.tmdl --serialization bim -o ./model.bim # convert formats
auth — authentication¶
auth login options:
| Option | Description |
|---|---|
-u, --username <id> |
Service-principal application (client) id. |
--password <source> |
Service-principal client secret source: pass - to read one line from stdin. Secret values on the command line are rejected. |
--password-file <file> |
Path to a file containing the client secret (trailing newline ignored). |
--tenant <tenant> |
Tenant id or domain (required for service principal). |
--certificate <file> |
Certificate file (PEM or PKCS12) for service-principal auth. |
--certificate-password <source> / --certificate-password-file <file> |
Certificate password via stdin (-) or file; plain values on the command line are rejected. |
-I, --identity |
Sign in with a managed identity (Azure-hosted; use --username for user-assigned). |
--device-code |
Use the device-code flow instead of a local browser. |
--client-id <id> |
Override the Azure AD client id used for interactive/device-code sign-in. |
--save |
Keep the service principal credentials for future sign-ins (default: true). --save false uses them for this login only. |
tx auth login # interactive browser login
tx auth login --device-code # no local browser (SSH, containers)
# Service principal — secret from stdin (CI) or a file, never argv
printf '%s' "$SECRET" | tx auth login -u $APP_ID --tenant $TENANT --password -
tx auth login -u $APP_ID --tenant $TENANT --password-file ./secret.txt
tx auth status
tx auth logout