unshackle moves your metrics, dashboards and permissions out of a BI tool and into files in a Git repository you own.
What you get
| You had in your BI tool | You get in your repo |
|---|---|
| Metrics, measures, calculated fields | Metrics in Apache Ossie, an open semantic-layer format (semantic/) |
| Dashboards | Jupyter notebooks: one SQL query and one chart per tile (notebooks/) |
| Tables and data sources | Table and column descriptions (catalog/) |
| Permissions, row-level security | Cedar policies and SQL row filters (policies/) |
| Descriptions, glossaries | Markdown (knowledge/) |
What unshackle can't translate faithfully is marked TODO(unshackle), with the
original formula next to it. It doesn't guess.
How it works
- Extract: reads definitions through your tool's API, or from files you download.
- Translate: writes the files above. Nothing changes in your BI tool.
- Report:
migration/report.mdshows, per dashboard, what was translated and what blocks the rest. - Check: compares the migrated queries with your tool's own numbers.
Get started
You need Python 3.11 or later and access to your BI tool.
pip install unshackle # or: uv tool install unshackle
cd your-analytics-repo
unshackle check <tool> --prompt # asks for credentials, saves them to .env (git-ignored)
unshackle migrate <tool>
Then:
unshackle run # run the notebooks; see which tiles return data
unshackle verify # compare migrated numbers with your tool's
unshackle todo # list what's left to finish
unshackle tools <tool> says where to find each credential.
Supported tools
| Tool | Maturity | Import files instead of the API |
|---|---|---|
| Tableau | Most complete | .twb, .twbx, .tds, .tdsx |
| Power BI | Real projects | Power BI project (.pbip, model as TMDL) |
| Looker | Real projects | LookML project (Git checkout or .zip) |
| Qlik Sense | Saved exports | qlik app unbuild folder per app |
| Amazon QuickSight | Saved exports | .qs asset bundle |
| Metabase | Saved exports | API only |
| Lightdash | Saved exports | dbt project folder |
| Apache Superset | Saved exports | export .zip |
| Redash | Saved exports | API only |
| Omni | Early | model YAML folder (Git sync) |
| Hex | Early | project YAML (Git export) |
| ThoughtSpot | Early | .tml files or Export TML .zip |
| Sigma | Early | API only |
Maturity: Most complete: the most translated and tested. Real projects: also tested on open-source projects people built. Saved exports: tested on exports over a fictional dataset. Early: the basics; expect more TODOs.
Each tool's page covers connecting, what you get, what's left to finish and how to check the numbers.
API or files
API gets the most: definitions, dashboards people built in the tool, usage, sharing, and for most tools the SQL the tool itself runs.
Files work when you can't get API credentials. They carry less (usually no usage or sharing, and for Looker and Omni no user-built dashboards); the report lists what's missing.
unshackle import <tool> <files or folder>
unshackle build <tool>
Data that lives only in your BI tool
Tableau extracts, Excel and CSV files have no warehouse behind them. migrate asks
whether to copy that data to data/ (git-ignored) so the notebooks can run on it
locally. Copying .hyper extracts needs Tableau's Hyper API, a large download:
pip install "unshackle[hyper]".
Check the numbers
unshackle verify runs the cases in migration/parity/ against your warehouse and
compares them with the source tool's numbers. For Tableau, unshackle verify --init tableau
writes the cases from Tableau's own view data. For other tools, write them by hand:
see the verify guide.
How it's tested
- Against numbers, not snapshots. Most tests build a migration from a saved export, run the generated SQL in DuckDB on a fictional dataset, and compare the result with the same numbers computed independently, following the source tool's own rules.
- About 1,270 tests run offline:
uv pip install -e ".[dev]" && pytest. unshackle verifydoes the same on your data: migrated SQL against your tool's own numbers.
unshackle is built with Claude Code; every change goes through those tests.
With a coding agent
unshackle runs fine on its own. If you use a coding agent (Claude Code, Codex,
Cursor), point it at the repo: AGENTS.md explains the layout, and the guides in
migration/skills/ walk it through finishing each kind of TODO.
Try it without a BI tool
git clone https://github.com/Querio-App/unshackle && cd unshackle
uv venv && uv pip install -e ".[dev]"
./examples/tableau-demo/run.sh /tmp/acme
The demo migrates a saved Tableau export into /tmp/acme and checks a dashboard's
numbers against Tableau's.
More
- Repo layout: every folder and file unshackle writes
- Contributing · Security · Changelog
- The name: why a BI migration tool is named after Shackleton
Apache 2.0. Built and maintained by Querio.
Metadata
Release files for unshackle 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| unshackle-0.1.0.tar.gz | 2.1 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unshackle-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.8 MB
Release files / unshackle-0.1.0.tar.gz
| Download URL | unshackle-0.1.0.tar.gz |
|---|---|
| Size | 2.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0bce50b5e8c457098653438dbc2b6d0d413f24f03fbf582d29e6fe84948fe700
|
|
BLAKE2b-256 checksum How to use checksums |
0bb2f982640282b14eebe7d518204b671716bba6cdd843016414aa8a3497cc8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logRelease files / unshackle-0.1.0-py3-none-any.whl
| Download URL | unshackle-0.1.0-py3-none-any.whl |
|---|---|
| Size | 629.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2881aa65f3c26c0d532b25dc1fb16cd224a9cfa2f04926985456620ff3c2a83c
|
|
BLAKE2b-256 checksum How to use checksums |
bc2efad5185082be82e7d6ed2c32fe7c94f60b7555f5e971407a23c8588f6c5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logSecurity for unshackle 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for unshackle-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.