Skip to content

About

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

295 Commits

Folders and files

Repository files navigation

Semantic Model Cleaner

Semantic Model Cleaner analyzes Power BI PBIR + TMDL projects, shows which semantic model items appear to be unused across selected reports, and lets you apply cleanup actions locally.

It works directly in repositories containing TMDL and PBIR files; Power BI Desktop is not required. Core workflows are free under the MIT license, with no account or paid service required. Fabric integration is a future extension.

It is designed for local use against files on your machine. Version 0.4.0b10 is the public beta for Power BI practitioners who already work with PBIR and TMDL.

Beta10 integrates format-string reference checks, whole-table dependencies, Broken-item deletion handling, nullable report bindings, Review explanations, and structural-unit retention. See the release notes.

Before applying changes: back up your Power BI Project or commit it to version control first. Apply writes to your TMDL and PBIR files; guarded restore recovers the original bytes from the plan, but a backup is your safety net.

Release candidate: publication and independent review are pending. Versioned download links below are release targets, not evidence of available artifacts.

Current Status

AI agents can use the repository's SKILL.md for command discovery, scope rules and the reviewed cleanup workflow. Maintainers regenerate it with python scripts/generate_skill.py after installing the project; CI checks it against smc capabilities with python scripts/generate_skill.py --check.

  • Project maturity: public beta 0.4.0b10
  • Runtime shape: Python package with a CLI, a local web UI, and Windows desktop packaging
  • Stable entry points: semantic-model-cleaner, semantic-model-cleaner-web, smc, and smc-web
  • Windows entry points: packaged Semantic Model Cleaner.exe, semantic-model-cleaner-desktop, and smc-desktop
  • Release channel: beta is baked into this package and shown in the UI

What It Does

  • Scans exactly one .SemanticModel and one or more .Report folders
  • Detects direct report usage plus supported indirect or model-backed usage
  • Surfaces warnings for unresolved or ambiguous dynamic references
  • Lets you review analysis results in a local web UI
  • Supports local cleanup actions such as move to folder, hide/unhide, and delete
  • Previews queued cleanup actions before writing TMDL files

What It Does Not Do

  • It does not host or publish reports for you
  • It does not yet ship a signed installer or auto-update flow
  • It does not yet cover every Power BI metadata edge case

Requirements

  • Windows ZIP: Windows x64; no Python installation required.
  • CLI or source install: Python 3.11+.

Install

The desktop VS Code extension preview is prepared for an initial public pre-release as MrPerfectH.semantic-model-cleaner 0.1.4. It wraps the existing Python/UI and requires a separately installed compatible engine. Nothing is installed automatically; see the extension instructions for engine setup, VSIX packaging and acceptance limits. Publication is a separate maintainer action.

Runtime install:

python -m pip install .

Development install:

python -m pip install -e .[dev]

Windows Packaged App

For terminal-free Windows use, download semantic-model-cleaner-windows-x64-0.4.0b10.zip and its SHA-256 checksum from the explicit beta prerelease. Extract the whole ZIP, then run Semantic Model Cleaner.exe. Python, Power BI Desktop, Fabric, an account, and paid services are not required.

Local launcher command:

semantic-model-cleaner-desktop .

Short alias:

smc-desktop .

Packaged runtime behavior:

  • starts the local app on 127.0.0.1
  • prefers port 5001 and falls back to another free local port if needed
  • opens the default browser automatically
  • can skip browser launch with --no-open-browser

Quick Start

Windows public beta

Open Try demo or Open Power BI Project, review the selected Semantic Model and connected Reports, then choose Analyze. Inspect one item’s Usage and dependencies before preparing changes. Review the exact file diff before apply. Changes & history provides file verification and guarded restore. See the Windows walkthrough.

CLI

Run smc --help for the complete command guide and smc --version for the installed version. The CLI automation contract documents JSON output, exit codes, path/filter differences, and a disposable reviewed-change workflow.

Ask focused questions with compact text output or versioned JSON for agents:

smc items . --search Revenue
smc usage . --table Sales --item Revenue
smc usage . --table Sales
smc summary .
smc review . --format json
smc capabilities

SMC normally discovers one Semantic Model and its connected Reports. For explicit selection, use --model-path Models/Sales.SemanticModel and repeatable --report-path Reports/Executive.Report. These are exact paths relative to the project argument (absolute paths also work) across project commands. Existing selectors retain their behavior; see selection and migration.

These source-version commands explain direct and indirect usage by Report, page, and visual, summarize each Report's model footprint, and group existing check findings. They are read-only; use --model-only when Report usage cannot be checked. See focused CLI queries and agent workflows.

Run the analyzer from a workspace root:

semantic-model-cleaner . --format full

Export JSON or Excel:

semantic-model-cleaner . --format json -o analysis.json
semantic-model-cleaner . --format xlsx -o analysis.xlsx

Short alias:

smc . --format full

Use explicit paths when your model and report roots are separate:

semantic-model-cleaner \
  --models-path /path/to/Model.SemanticModel \
  --reports-path /path/to/Report.Report \
  --format unused

Module entrypoint:

python3 -m semantic_model_cleaner . --format full

CLI: clean-stale

clean-stale previews dead PBIR metadata in bulk: stale visual selectors, stale bookmark projections and stale formatting rules. These are the warning issues the analyzer already marks with a high-confidence clean_stale suggestion, because the reference is not part of the live visual query. Broken references (missing_table, missing_column, missing_measure — severity error, i.e. rename fallout) are never touched.

smc clean-stale .                                   # dry run: counts + full candidate list
smc clean-stale . --kind formatting selector        # limit to some kinds
smc clean-stale . --format json                     # machine-readable

By default it analyzes only the reports whose definition.pbir binds them to the selected semantic model (by path, or by published name for live connections) — the same invariant the web UI's report finder applies; pass --all-reports to analyze every discovered report, and note that --report filters compose on top of the bound set.

The positional argument is project_path — the Power BI Project folder that holds one .SemanticModel and its .Report folders (default .). It takes the same selection flags as the analyzer (--models-path, --reports-path, --model, --report).

Exit codes (so CI can gate on a dry run):

Code Meaning
0 No cleanup candidates
1 Cleanup candidates found; nothing was written
2 Input/analysis error or a withheld direct-write request

This command is read-only in the beta. The legacy --apply shortcut is withheld because it cannot apply a previously reviewed, saved plan. Use the app change review or a clean_stale operation through CLI plans, followed by smc diff, smc apply and smc verify. The reviewed workflow always records recovery data.

Local Web UI

Start the web app:

semantic-model-cleaner-web .

Short alias:

smc-web .

Then open http://127.0.0.1:5001.

Optional flags:

semantic-model-cleaner-web . --port 8080
semantic-model-cleaner-web . --host localhost
semantic-model-cleaner-web . --debug

Module entrypoint:

python3 -m semantic_model_cleaner.web .

The web app is local-only: both launchers accept 127.0.0.1 or localhost, and remote binding is disabled. The workspace handles the per-launch request token automatically. Local scripted HTTP clients must first read /api/session, then send its token in the X-SMC-Token header; use JSON for changes. CLI file-based commands need no HTTP token. See local HTTP access for the supported client protocol and browser boundary.

Demo Workspace

The app bundles a small synthetic demo workspace. In the web UI, click Try the demo workspace to copy it to ~/.semantic-model-cleaner/demo-workspace and analyze it — no Power BI Project files of your own are needed, and the bundled copy is never modified. The source lives under src/semantic_model_cleaner/demo_workspace and also supports screenshots, quick validation, and safe public examples.

A richer synthetic QA workspace is available under examples/product-qa-workspace. It exercises trust-critical flows such as Report Health, stale report metadata, broken references, Unsupported Metadata review downgrades, RLS-backed dependencies, and Report Extension Measures.

Supported Exports

  • CLI: json, xlsx
  • Web UI: Export JSON, Export Excel

Both web exports download the latest completed analysis without re-running it.

CLI exports (full, unused, json, and xlsx) must be saved outside Semantic Model and Report artifact folders, including artifacts excluded from the analysis. This also applies to Excel's default output in the current directory. Use --output to choose an external directory; unsafe destinations return exit code 2 without writing project files. Resolved symlink/junction aliases are checked, and existing files with multiple hard links are rejected; choose a new output file instead. Ordinary external export files can still be overwritten.

Safety Notes

  • The workflow is intentionally 1 semantic model -> 1 or more reports
  • UI and CLI changes use saved plans with exact previews, validation, source fingerprints and guarded apply
  • Every applied plan records a receipt and original bytes for guarded restore; legacy direct-write HTTP routes are withheld
  • Field parameters backed by NAMEOF(...) are supported
  • Calculation groups are recognized (type, items, selector column, retained parent-table DAX consumers); calculation item expressions remain Analysis limitations and keep unused items at Review
  • Culture translations are read structurally as per-object Translation Membership (culture, file and line), shown as informational evidence that never changes the Cleanup Recommendation; linguisticMetadata remains an Analysis Limitation owned by its culture
  • Auto-date tables (analysis summary): one group-level result for Power BI generated LocalDateTable_* / DateTableTemplate_* tables. Either "N auto-date tables detected. All can be removed." with one Preview removal of all auto-date tables action, or "Cannot remove all: dependencies were found [or coverage could not be confirmed]. Nothing will be removed." with a short grouped reason. All or nothing: there is no per-table choice, and the server refuses table lists and older per-table plans. Every table must match the generated structure and have no use in the selected model and reports, including Q&A linguistic metadata (Q&A keys in a letter case other than Power BI Desktop's also block). Their relationships, ref table lines and date-column variations go with them; the date columns stay. The Auto date/time setting is not changed
  • Delete and rename plans include dependent perspective members and culture translations in their file diffs and recovery data. Unrecognized or malformed perspective/culture structure blocks the plan with a file-specific explanation; expression payloads such as linguistic metadata remain unchecked
  • Usage states: the web app separates Used, Indirect, Stale only (referenced only by stale report metadata) and Unused. The CLI --format unused list and the JSON summary.not_used total include Stale only items, so they can exceed the web app's "Not used" count by exactly those items
  • Analysis limitations are listed separately from Report Health with distinct-limitation and affected-item counts; remaining caveats include broader metadata indirection and malformed or skipped JSON

Development

Run tests:

python3 -m pytest

Run lint:

python3 -m ruff check .

Build distributions:

python3 -m build

Build the Windows package locally:

pwsh -File packaging/windows/build.ps1

Public beta channel

  • Version 0.4.0b10 defaults to the beta release channel without an environment variable.
  • Developers can set SMC_RELEASE_CHANNEL=stable to inspect the stable-gated UI during compatibility testing.
  • The public beta shows a Beta banner. Experiments remain separately opt-in.

No experimental features are currently registered. See tests/test_experiments.py for release-channel logic.

See the five-minute repository quick start, CI check contract, and support matrix.

Repository Layout

  • src/semantic_model_cleaner/analyzer.py: CLI analyzer and export logic
  • src/semantic_model_cleaner/webapp.py: Flask app and API
  • src/semantic_model_cleaner/tmdl_writer.py: TMDL edit engine
  • src/semantic_model_cleaner/templates/index_v2.html: single-page workspace UI template
  • src/semantic_model_cleaner/demo_workspace/: bundled synthetic demo workspace
  • examples/product-qa-workspace/: richer synthetic QA workspace
  • scripts/analyze_model_usage.py: compatibility wrapper for the packaged CLI
  • scripts/app.py: compatibility wrapper for the packaged web app
  • tests/: automated tests and fixtures

Contributing

Contribution guidance is documented in CONTRIBUTING.md.

Roadmap

Planned follow-up work is tracked in BACKLOG.md.

More Detail

Analyzer-specific usage and caveats are documented in scripts/analyze_model_usage.README.md.

Community & Support

Reviewed CLI changes

The CLI and web UI share a staged change-plan engine for model cleanup, renames, measure moves, report extension measure deletion, report-measure promotion and report repairs. Prepare a plan from an operations JSON file, inspect its exact differences, then apply it with freshness checks and a recovery journal:

smc plan /path/to/project --operations operations.json -o review/change.plan.json
smc diff review/change.plan.json
smc apply review/change.plan.json
smc verify review/change.plan.json

Use smc history to inspect receipts and smc restore review/change.plan.json for guarded recovery. Plans contain local metadata and must come from a trusted source. Static validation covers supported selected files; it does not evaluate Power BI runtime behavior. See CLI plans and recovery for operation examples, scope rules, exit codes and interrupted-operation recovery.

Read CI checks and baselines, supported workflows, and the beta quick start.

External/saved .dax queries (including developer scratch and DAXQueries files) are outside semantic-model and report cleanup scope. They are not analyzed, fingerprinted, staged, changed or restored. Query edits, additions and deletions do not invalidate a cleanup plan. Model TMDL expressions and report-extension DAX remain analyzed.

Scratch query scope includes the exact DAXQueries/.pbi/daxQueries.json editor index. Its contents, including unsupported or malformed state, do not affect cleanup eligibility, coverage or plan drift. Apply and restore preserve concurrent scratch edits, additions and deletions. Declared report resources and files in StaticResources keep their resource guards regardless of extension (including .dax); a declaration that collides with the editor-index path takes precedence. Other JSON and .pbi metadata remain guarded.

About

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages