Metadata-Version: 2.5
Name: unshackle
Version: 0.1.0
Summary: Move your metrics, dashboards and permissions out of a BI tool and into files in a Git repository you own.
Project-URL: Repository, https://github.com/Querio-App/unshackle
Project-URL: Issues, https://github.com/Querio-App/unshackle/issues
Project-URL: Changelog, https://github.com/Querio-App/unshackle/blob/main/CHANGELOG.md
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: altair>=5.4
Requires-Dist: boto3>=1.34
Requires-Dist: click>=8.1
Requires-Dist: duckdb-engine>=0.13
Requires-Dist: duckdb>=1.0
Requires-Dist: httpx>=0.27
Requires-Dist: ipykernel>=6.29
Requires-Dist: lkml>=1.3
Requires-Dist: nbclient>=0.10
Requires-Dist: nbformat>=5.9
Requires-Dist: openpyxl>=3.1
Requires-Dist: pandas>=2.2
Requires-Dist: pyyaml>=6.0
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: websockets>=13
Provides-Extra: dev
Requires-Dist: jsonschema>=4.18; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: sqlglot>=25; extra == 'dev'
Requires-Dist: tableauhyperapi>=0.0.26479; extra == 'dev'
Provides-Extra: hyper
Requires-Dist: tableauhyperapi>=0.0.26479; extra == 'hyper'
Description-Content-Type: text/markdown

<h1 align="center">
  <img src="https://raw.githubusercontent.com/Querio-App/unshackle/main/assets/banner.svg" alt="unshackle" width="760">
</h1>

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](https://github.com/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](https://www.cedarpolicy.com) 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

1. **Extract:** reads definitions through your tool's API, or from files you download.
2. **Translate:** writes the files above. Nothing changes in your BI tool.
3. **Report:** `migration/report.md` shows, per dashboard, what was translated and what blocks the rest.
4. **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.

```bash
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:

```bash
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](https://github.com/Querio-App/unshackle/blob/main/docs/tools/tableau.md) | Most complete | `.twb`, `.twbx`, `.tds`, `.tdsx` |
| [Power BI](https://github.com/Querio-App/unshackle/blob/main/docs/tools/powerbi.md) | Real projects | Power BI project (`.pbip`, model as TMDL) |
| [Looker](https://github.com/Querio-App/unshackle/blob/main/docs/tools/looker.md) | Real projects | LookML project (Git checkout or `.zip`) |
| [Qlik Sense](https://github.com/Querio-App/unshackle/blob/main/docs/tools/qlik.md) | Saved exports | `qlik app unbuild` folder per app |
| [Amazon QuickSight](https://github.com/Querio-App/unshackle/blob/main/docs/tools/quicksight.md) | Saved exports | `.qs` asset bundle |
| [Metabase](https://github.com/Querio-App/unshackle/blob/main/docs/tools/metabase.md) | Saved exports | API only |
| [Lightdash](https://github.com/Querio-App/unshackle/blob/main/docs/tools/lightdash.md) | Saved exports | dbt project folder |
| [Apache Superset](https://github.com/Querio-App/unshackle/blob/main/docs/tools/superset.md) | Saved exports | export `.zip` |
| [Redash](https://github.com/Querio-App/unshackle/blob/main/docs/tools/redash.md) | Saved exports | API only |
| [Omni](https://github.com/Querio-App/unshackle/blob/main/docs/tools/omni.md) | Early | model YAML folder (Git sync) |
| [Hex](https://github.com/Querio-App/unshackle/blob/main/docs/tools/hex.md) | Early | project YAML (Git export) |
| [ThoughtSpot](https://github.com/Querio-App/unshackle/blob/main/docs/tools/thoughtspot.md) | Early | `.tml` files or Export TML `.zip` |
| [Sigma](https://github.com/Querio-App/unshackle/blob/main/docs/tools/sigma.md) | 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.

```bash
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](https://github.com/Querio-App/unshackle/blob/main/skills/verify/SKILL.md).

## 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 verify` does the same on your data: migrated SQL against your tool's own numbers.

unshackle is built with [Claude Code](https://claude.com/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

```bash
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](https://github.com/Querio-App/unshackle/blob/main/spec/layout.md): every folder and file unshackle writes
- [Contributing](https://github.com/Querio-App/unshackle/blob/main/CONTRIBUTING.md) · [Security](https://github.com/Querio-App/unshackle/blob/main/SECURITY.md) · [Changelog](https://github.com/Querio-App/unshackle/blob/main/CHANGELOG.md)
- [The name](https://github.com/Querio-App/unshackle/blob/main/docs/name.md): why a BI migration tool is named after Shackleton

Apache 2.0. Built and maintained by [Querio](https://querio.ai).
