Saikiran Andey
All projects

Tableau Workbook Auditor

Built a .twbx auditor that runs entirely in the browser with no backend, so the workbook is never uploaded; it flags unused fields and duplicate calculations and diffs up to 5 workbook versions. Shipped the same engine as an 11-tool MCP server on npm, the official MCP Registry, a Claude Desktop extension and a Claude Code plugin.

The lineage graph tableau-lineage.com draws for its sample workbook: parameters, calculated fields, raw fields and worksheets as linked nodes.
Its sample workbook, traced in the tab. Captured from tableau-lineage.com.

The problem

Inheriting someone else’s Tableau workbook means tracing calculated fields by hand to answer one question: where does this number come from, and what breaks if I change it? The tools that answer that run only inside Tableau, or ask you to upload the file. I wanted one that reads the file itself and never needs to send it anywhere.

Constraints

  • The workbook never leaves the machine: no backend, no upload, no cookies.
  • Workbooks up to 500 MB, as long as the XML inside stays under 250 MB.

How it is built

A .twbx is a ZIP. The tool unzips only the workbook XML, leaves the packaged data extract untouched, and parses the XML once in your browser. From that one model it builds the lineage graph, the audit, filters, dashboards, stored SQL and a semantic diff.

There is no backend, and the Content-Security-Policy only allows connections back to the site and its anonymous page-view counter, so the file has nowhere to go.

  1. Unzip the workbook XML onlyfflate opens the .twbx and takes only the .twb entry.
  2. Parse the XML onceDOMParser reads the workbook into one model.
  3. Resolve captions per data sourceEach formula’s field names resolve against the data source that owns it.Fixed here
  4. One modelCalculations, dependencies, parameters, filters, dashboards and stored SQL.
  5. Audit, lineage, diffUnused fields by confidence, duplicate calculations, 15 static performance rules, and a semantic diff.
  6. Browser app and MCP serverThe same engine in the tab and behind 11 read-only tools on npm.

What it checks

Unused fields are graded by confidence (unused, likely unused, mentioned only in a comment) with the reason spelled out, because a workbook file can’t prove a field is unused everywhere. It finds identical formulas under different names, and the riskier case of one name carrying different formulas. It runs 15 static performance rules. It compares up to five versions of a workbook and reports a rename as a rename.

MCP

I noticed I was pasting formulas into an AI chat one at a time, so I put the same engine behind an MCP server. I kept it local on purpose: a hosted server would mean uploading the workbook, which is the one thing the tool exists to avoid. It reads the file from your own disk and exposes 11 read-only tools.

  • analyze_workbook
  • audit_workbook
  • diff_workbooks
  • list_calculated_fields
  • get_field
  • trace_dependencies
  • list_parameters
  • get_lineage_graph
  • list_sql_queries
  • list_filters
  • list_worksheets

What broke, and the fix

In the step Resolve captions per data source

Before the fix

SUM([Net Sales]) · Gross Sales: unused, highest confidence

After the fix

SUM([Gross Sales]) · Gross Sales: used by A Total

Caught by my own pre-release audit. Fixed and shipped with regression tests. 446c9da, 2026

Other things that broke

  • Formulas reference parameters by caption while the internal name differs, which leaked a phantom dependency.
  • TOTAL inside a field called total_views made an ordinary field look like a table calculation.
  • A field mentioned only in a comment counted as used.
  • Same-named fields from different data sources, such as [Sales], were fused into one lineage node.
  • Every worksheet carries a list shaped like the real data-source block, so one data source was counted thirteen times on a twelve-sheet workbook.

Run it here

tableau-lineage’s published audit code, running on the demo workbook in this tab. Nothing is uploaded, and the page counts its own network requests while the audit runs.

On the demo workbook, the engine in your tab finds 7 fields and parameters flagged as unused (5 unused, 2 likely unused), 23% of the workbook, 0 duplicates, 4 performance findings, and a 25-node lineage graph with 24 edges.

Running it needs JavaScript. Everything above reads without it.

Loading the bench