A common ask from teams evaluating Sigma is migrating their Looker footprint — usually to take advantage of all the amazing things Sigma offers. The conversion itself can be a blocker — and the part this QuickStart automates.
The usual Looker-to-Sigma migration loop is rebuild-the-LookML-by-hand, rewrite every measure and derived dimension as a Sigma formula, recreate each dashboard tile, line the layout up against the source, then eyeball the numbers and hope nothing drifted in the translation. Done on a single dashboard it's tedious. Across a whole Looker instance with dozens of dashboards reading from shared explores, it's the reason migration projects slip.
This QuickStart walks through a Claude Code skill called looker-to-sigma that automates the loop.
Point it at a Looker dashboard (user-defined or LookML-defined); it reads the LookML model and dashboard JSON via the Looker REST API 4.0, translates the measures, dimensions, and derived calculations into Sigma formulas, builds a Sigma data model from the warehouse tables the LookML model points at, mirrors the dashboard's layout on Sigma's grid, and runs a parity pass that compares Sigma's chart output to Looker's live results. It surfaces a punch list of anything it couldn't auto-translate — instead of silently producing a broken workbook.
For the demonstration, we'll run the skill end-to-end against a Looker dashboard called Retail Performance Overview, built on a csa_thelook LookML model — six joined views (order_fact + customer_dim + product_dim + store_dim + order_date + promo_dim) over a retail star:

You'll see the discovery artifacts each phase produces, the converter's breakdown of how each Looker measure mapped to a Sigma formula, the parity report against the live warehouse, and the resulting Sigma data model and workbook landed in your org — along with the gap list of items to hand-polish.
A pure lift-and-shift is the floor, not the ceiling. The same skill family supports three follow-on moves that turn a migration into an upgrade:
Sigma SEs, technical CSMs, and migration partners running Looker-to-Sigma conversions — or scoping a batch migration with the companion looker-assessment skill.
Claude Code installed (CLI or desktop).Admin > Users > pick your user > Edit Keys > New API3 Key). The credential's user needs at least: read access to models, dashboards, and query execution.Develop view in Looker shows the configured remote URL. If your project lives in Looker's bundled git, you'll need to push to a remote (GitHub, GitLab, etc.) you can clone from.Python 3.10 or newer. macOS's stock system Python is typically 3.9 — older than the skill needs. If python3 --version reports anything below 3.10, install a newer interpreter via Homebrew (brew install python@3.12) or python.org.Node.js (any recent LTS) for building the converter MCP. The conversion uses a separate MCP server, sigma-data-model-mcp, cloned + built (npm install && npm run build) into ~/Desktop/sigma-data-model-mcp. The skill prompts you to install it mid-conversion — no upfront work needed — but pre-build it if you'd rather skip the gate.
looker-to-sigma is one of two skills that ship together as a single repo (cloned in the next section). Most of this QuickStart focuses on the converter — but knowing where the assessment skill fits saves dead ends later when scoping a batch migration.
Skill | Role | When to reach for it |
| Scoping | Auditing a Looker instance before committing to a conversion plan. Emits a per-dashboard complexity readout (LookML measure convertibility, tile-type coverage, derived-table flags, model size), usage signal from |
| Conversion | The subject of this QuickStart. Converts a single Looker dashboard (or a batch via shortlist) to a Sigma data model and matching workbook with verified data parity. |
Here's how the two skills connect in a full migration — looker-assessment hands the converter a ranked shortlist, and looker-to-sigma produces the Sigma workbooks with a verified parity report:

Not every migration needs both skills. Use the table below to map your scenario to the smallest set that fits.
In this QuickStart we're in the first row — one Looker dashboard whose LookML model reads from warehouse tables that we'll land in Snowflake — then run looker-to-sigma.
Your situation | Skill(s) to use |
1 dashboard, LookML reads from your warehouse |
|
1 dashboard, LookML reads from a warehouse Sigma can't connect to | Land the data in your warehouse first (covered in |
10+ dashboards (any data source) |
|
Auditing Looker sprawl without converting yet |
|

First we need to clone the skill's GitHub repository, configure Looker API credentials, capture your Sigma credentials, and clone your LookML project locally.
The two skills live in sigmacomputing/quickstarts-public under looker-migration-skills/.
From a terminal, run each command below one at a time so you can confirm each step before moving on.
Step 1: Create a local folder for the clone
mkdir -p ~/quickstarts-public
Step 2: Move into the new folder
cd ~/quickstarts-public
Step 3: Clone the repo without pulling any files yet
git clone --filter=blob:none --sparse https://github.com/sigmacomputing/quickstarts-public.git .
Step 4: Fill in only the looker-migration-skills folder
git sparse-checkout set looker-migration-skills
Step 5: Symlink looker-to-sigma into the Claude skills folder
ln -s ~/quickstarts-public/looker-migration-skills/looker-to-sigma ~/.claude/skills/looker-to-sigma
Step 6: Symlink looker-assessment
ln -s ~/quickstarts-public/looker-migration-skills/looker-assessment ~/.claude/skills/looker-assessment
Steps 5 and 6 should return with no error.

Step 7: Install the Python dependency the skill uses.
The skill reads LookML (a text-based modeling language) with PyYAML. Everything else is in Python's standard library.
python3 -m pip install pyyaml

Step 8: Capture your Sigma API credentials.
This script prompts for SIGMA_BASE_URL, SIGMA_CLIENT_ID, and SIGMA_CLIENT_SECRET and writes them into Claude's settings.
Run once per machine.
ruby ~/.claude/skills/looker-to-sigma/scripts/setup.rb

Step 9: Configure Looker API auth.
The skill reads ~/.looker/looker.ini for Looker REST API 4.0 credentials. Create it with your tenant URL, API3 client ID, and client secret:
mkdir -p ~/.looker && cat > ~/.looker/looker.ini <<'INI'
[Looker]
base_url=https://<your-instance>.cloud.looker.com:19999
client_id=<API3 client_id>
client_secret=<API3 client_secret>
verify_ssl=True
INI
Substitute your tenant URL and the API3 credentials you generated under Admin > Users > your user > Edit Keys.
Verify auth works:
python3 ~/.claude/skills/looker-to-sigma/scripts/looker_api.py whoami
You should see your Looker user's display name and roles.

Step 10: Clone your LookML project locally.
The skill needs to read your LookML model + view files from disk. Find the Git remote URL in Looker's Develop view → Projects → your project → Configure Git, then clone it somewhere you'll remember:
git clone <your-lookml-project-git-url> ~/lookml-projects/<project-name>
If your project lives in Looker's bundled git (the default for new trials), you'll first need to add a remote (GitHub, GitLab, etc.) and push from Looker so you have something to clone from.

Step 11: Verify Claude Code can invoke the skill.
Type claude in your terminal to start Claude Code, then invoke the skill:
claude
/looker-to-sigma
Claude should start reading the reference files and ask what dashboard you want to convert.
Pause at that prompt — we'll hand it everything in one shot via the kickoff prompt in Run the Conversion:


The Looker model we're migrating reads from a six-table retail star — one fact (ORDER_FACT) joined LEFT_OUTER to five dimensions (CUSTOMER_DIM, PRODUCT_DIM, STORE_DIM, DATE_DIM, PROMO_DIM). For the migration to land in Sigma cleanly, the same six tables need to exist in a connection your Sigma org can reach. Approximate row counts: 681 / 25 / 25 / 15 / 1,096 / 23.
Data prep has two halves:
COPY INTO statements below read from S3 directly — no local download needed.USE ROLE ACCOUNTADMIN;
USE WAREHOUSE COMPUTE_WH;
CREATE DATABASE IF NOT EXISTS QUICKSTARTS;
CREATE SCHEMA IF NOT EXISTS QUICKSTARTS.LOOKER_RETAIL_ANALYTICS;
USE SCHEMA QUICKSTARTS.LOOKER_RETAIL_ANALYTICS;
CREATE OR REPLACE FILE FORMAT csv_format
TYPE = CSV
FIELD_DELIMITER = ','
SKIP_HEADER = 1
FIELD_OPTIONALLY_ENCLOSED_BY = '"'
NULL_IF = ('', 'NULL')
EMPTY_FIELD_AS_NULL = TRUE;
CREATE OR REPLACE STAGE looker_retail_stage
URL = 's3://sigma-quickstarts-main/Looker/'
FILE_FORMAT = csv_format;
CREATE OR REPLACE TABLE ORDER_FACT (
ORDER_ID VARCHAR,
ORDER_LINE NUMBER(38,0),
CUSTOMER_KEY NUMBER(38,0),
PRODUCT_KEY NUMBER(38,0),
ORDER_STORE_KEY NUMBER(38,0),
SHIP_STORE_KEY NUMBER(38,0),
PROMO_KEY NUMBER(38,0),
ORDER_DATE_KEY NUMBER(38,0),
SHIP_DATE_KEY NUMBER(38,0),
RETURN_DATE_KEY NUMBER(38,0),
ORDER_CHANNEL VARCHAR,
SHIP_METHOD VARCHAR,
ORDER_STATUS VARCHAR,
QUANTITY_ORDERED NUMBER(38,0),
QUANTITY_RETURNED NUMBER(38,0),
UNIT_PRICE NUMBER(38,2),
UNIT_COST NUMBER(38,2),
DISCOUNT_AMOUNT NUMBER(38,2),
SHIPPING_AMOUNT NUMBER(38,2),
TAX_AMOUNT NUMBER(38,2),
GROSS_REVENUE NUMBER(38,2),
NET_REVENUE NUMBER(38,2),
GROSS_PROFIT NUMBER(38,2),
NET_PROFIT NUMBER(38,2),
IS_FIRST_ORDER NUMBER(1,0),
IS_RETURNED NUMBER(1,0),
IS_CANCELLED NUMBER(1,0),
DAYS_TO_SHIP NUMBER(38,0)
);
CREATE OR REPLACE TABLE CUSTOMER_DIM (
CUSTOMER_KEY NUMBER(38,0),
CUSTOMER_ID VARCHAR,
FIRST_NAME VARCHAR,
LAST_NAME VARCHAR,
EMAIL VARCHAR,
PHONE VARCHAR,
CITY VARCHAR,
STATE VARCHAR,
ZIP_CODE VARCHAR,
REGION VARCHAR,
CUSTOMER_SEGMENT VARCHAR,
LOYALTY_TIER VARCHAR,
ACQUISITION_CHANNEL VARCHAR,
FIRST_ORDER_DATE DATE,
IS_ACTIVE NUMBER(1,0),
IS_EMAIL_OPT_IN NUMBER(1,0),
LIFETIME_ORDER_COUNT NUMBER(38,0),
LIFETIME_REVENUE NUMBER(38,2)
);
CREATE OR REPLACE TABLE PRODUCT_DIM (
PRODUCT_KEY NUMBER(38,0),
PRODUCT_ID VARCHAR,
PRODUCT_NAME VARCHAR,
CATEGORY VARCHAR,
SUBCATEGORY VARCHAR,
BRAND VARCHAR,
UNIT_COST NUMBER(38,2),
UNIT_PRICE NUMBER(38,2),
WEIGHT_LBS NUMBER(38,2),
IS_ACTIVE NUMBER(1,0),
IS_PRIVATE_LABEL NUMBER(1,0),
IS_SEASONAL NUMBER(1,0),
LAUNCH_DATE DATE,
DISCONTINUE_DATE DATE,
"Product_Key/Name" VARCHAR
);
CREATE OR REPLACE TABLE STORE_DIM (
STORE_KEY NUMBER(38,0),
STORE_ID VARCHAR,
STORE_NAME VARCHAR,
STORE_TYPE VARCHAR,
CITY VARCHAR,
STATE VARCHAR,
REGION VARCHAR,
DISTRICT VARCHAR,
SQUARE_FOOTAGE NUMBER(38,0),
OPEN_DATE DATE,
CLOSE_DATE DATE,
IS_ACTIVE NUMBER(1,0),
HAS_CAFE NUMBER(1,0),
HAS_CURBSIDE NUMBER(1,0),
MANAGER_NAME VARCHAR,
STORE_PHONE VARCHAR,
ANNUAL_LEASE_COST NUMBER(38,2)
);
CREATE OR REPLACE TABLE DATE_DIM (
DATE_KEY NUMBER(38,0),
FULL_DATE DATE,
DAY_OF_WEEK VARCHAR,
DAY_OF_MONTH NUMBER(38,0),
WEEK_OF_YEAR NUMBER(38,0),
MONTH_NUMBER NUMBER(38,0),
MONTH_NAME VARCHAR,
QUARTER NUMBER(38,0),
"YEAR" NUMBER(38,0),
IS_WEEKEND NUMBER(1,0),
IS_HOLIDAY NUMBER(1,0),
FISCAL_PERIOD VARCHAR
);
CREATE OR REPLACE TABLE PROMO_DIM (
PROMO_KEY NUMBER(38,0),
PROMO_ID VARCHAR,
PROMO_NAME VARCHAR,
PROMO_TYPE VARCHAR,
CHANNEL VARCHAR,
DISCOUNT_PCT NUMBER(38,2),
START_DATE DATE,
END_DATE DATE,
MIN_ORDER_AMOUNT NUMBER(38,2),
IS_STACKABLE NUMBER(1,0),
TARGET_SEGMENT VARCHAR,
PROMO_COST NUMBER(38,2)
);
COPY INTO ORDER_FACT FROM @looker_retail_stage/ORDER_FACT.csv ON_ERROR = ABORT_STATEMENT;
COPY INTO CUSTOMER_DIM FROM @looker_retail_stage/CUSTOMER_DIM.csv ON_ERROR = ABORT_STATEMENT;
COPY INTO PRODUCT_DIM FROM @looker_retail_stage/PRODUCT_DIM.csv ON_ERROR = ABORT_STATEMENT;
COPY INTO STORE_DIM FROM @looker_retail_stage/STORE_DIM.csv ON_ERROR = ABORT_STATEMENT;
COPY INTO DATE_DIM FROM @looker_retail_stage/DATE_DIM.csv ON_ERROR = ABORT_STATEMENT;
COPY INTO PROMO_DIM FROM @looker_retail_stage/PROMO_DIM.csv ON_ERROR = ABORT_STATEMENT;
GRANT USAGE ON DATABASE QUICKSTARTS TO ROLE SIGMA_SERVICE_ROLE;
GRANT USAGE ON SCHEMA QUICKSTARTS.LOOKER_RETAIL_ANALYTICS TO ROLE SIGMA_SERVICE_ROLE;
GRANT SELECT ON ALL TABLES IN SCHEMA QUICKSTARTS.LOOKER_RETAIL_ANALYTICS TO ROLE SIGMA_SERVICE_ROLE;
GRANT SELECT ON FUTURE TABLES IN SCHEMA QUICKSTARTS.LOOKER_RETAIL_ANALYTICS TO ROLE SIGMA_SERVICE_ROLE;
-- Sanity-check row counts. Expected: 681 / 25 / 25 / 15 / 1096 / 23.
SELECT 'ORDER_FACT' AS TABLE_NAME, COUNT(*) AS ROW_COUNT FROM ORDER_FACT UNION ALL
SELECT 'CUSTOMER_DIM', COUNT(*) FROM CUSTOMER_DIM UNION ALL
SELECT 'PRODUCT_DIM', COUNT(*) FROM PRODUCT_DIM UNION ALL
SELECT 'STORE_DIM', COUNT(*) FROM STORE_DIM UNION ALL
SELECT 'DATE_DIM', COUNT(*) FROM DATE_DIM UNION ALL
SELECT 'PROMO_DIM', COUNT(*) FROM PROMO_DIM;
-- Net Revenue baseline (~$114,079.95 for the warehouse snapshot).
SELECT TO_CHAR(SUM(NET_REVENUE), '$999,999,999.99') AS TOTAL_NET_REVENUE
FROM ORDER_FACT;
If the load completes cleanly, the row-count check returns 681 / 25 / 25 / 15 / 1096 / 23 and the Net Revenue check returns roughly $114,079.95. Any mismatch means either a COPY partial-load error (check Snowflake's load history) or a different S3 file than expected.


The converter needs a Sigma folder to land the new data model and workbook in. The skill will ask for the folder's UUID — it will be easier to have it ready before you return to the Claude prompt that's still paused after the skill loaded.
To keep this simple, we will use a plain folder and not a workspace.
Step 1: Create (or pick) a folder in Sigma.
Open your Sigma org, navigate to where you want the migrated workbook to live, and create a folder for it. Something like:
Looker Migration Demo
Step 2: Grab the folder ID.
Open the folder. The ID is the last segment of the URL — a short alphanumeric string, 21 characters. Copy it from the address bar and keep it on the clipboard for the next section.


The skill can run interactively, asking for the dashboard, LookML directory, warehouse, and Sigma destination one at a time. For a known target — like ours — it's faster to give Claude the entire job in one message. The skill recognizes a structured kickoff prompt and assembles the migrate-looker.py command directly, going straight from "go" through discover → convert → data model → workbook build → layout → parity.
If Claude is still running and paused at the skill's first prompt from Install and Configure the Skill, return to that terminal. If you closed Claude after that step, restart it now:
claude
/looker-to-sigma
When Claude finishes loading the skill and asks what to migrate, choose Chat about this:

Paste the block below. Substitute your own values where the placeholders are:
LookML directory — the local clone path from Install Step 10Dashboard ID — the numeric ID or slug of the Looker dashboard you want to migrate (visible in the dashboard's URL: /dashboards/)SIGMA_CONNECTION_ID — your Snowflake connection ID from Sigma's Administration > ConnectionsSIGMA_FOLDER_ID — the folder ID you copied at the end of the previous sectionRun /looker-to-sigma on the following. Use migrate-looker.py end-to-end and stop only if a hard gate fails.
Looker
- ~/.looker/looker.ini is configured with API3 credentials
- LookML directory: <local-path-to-cloned-lookml-project>
- Dashboard ID: <looker-dashboard-id-or-slug>
Warehouse (Snowflake)
- Database: QUICKSTARTS
- Schema: LOOKER_RETAIL_ANALYTICS
Sigma
- SIGMA_API_TOKEN = mint from ~/.sigma-migration/env
- SIGMA_CONNECTION_ID: <your-snowflake-connection-id>
- SIGMA_FOLDER_ID: <your-folder-id>
Options
- Name prefix: Looker Retail Analytics
- Auto-approve mid-pipeline questions: yes
- Parity: tolerate row-count drift between Looker (live) and the warehouse snapshot — this QuickStart uses a frozen CSV copy of the source. Report the delta with a row-level diff, but treat warehouse-snapshot staleness as a soft fail (not a gate-red).
Don't declare GREEN until the parity gate passes (or the tolerance above applies) and the visual-QA loop passes.
Claude reads the block, mints a fresh Sigma token from ~/.sigma-migration/env, assembles the migrate-looker.py command with the right flags, and runs it end-to-end. The rest of the run is hands-off until a gate or decision point.

When the migration completes, Claude prints a final summary covering the whole pipeline — every phase's result, the visual-QA outcome, the hard-gate verdict, and the URLs of the new Sigma data model and workbook:

The summary walks through six phases plus a visual-QA pass:
PASS within tolerance or FAIL; the gate is GREEN only when all charts pass.Open the new workbook in Sigma to see the migrated dashboard:

Open the data model to see how the converter wired up the joins and metrics.

Hand-polish items the skill flags rather than silently working around:
merged_results are listed in the summary; hand-author the Sigma equivalent on the affected element.listen blocks) translates to Sigma controls when the targets resolve cleanly; the skill surfaces any controls it couldn't auto-wire.
A single dashboard is the easy case. Real migrations involve Looker instances with dozens or hundreds of dashboards reading from a handful of shared explores — and migrating them one-by-one through the converter loses the leverage of doing the planning work once. That's where the companion looker-assessment skill comes in.
Point looker-assessment at a Looker instance and it inventories every model, explore, dashboard, and look, scoring each on:
system__activity model (Looker's built-in usage data), used to flag cold and zero-view content for retirement instead of migrationThe output is a Sigma-branded readout.html you can share with stakeholders, plus a ranked migration shortlist sorted by value / (1 + cost) — the cheapest, highest-value dashboards to convert first, with tag pills like migrate-first, easy-win, needs-review, and retire.
The shortlist becomes input to a batch conversion plan — looker-assessment groups dashboards that share the same explore so one Sigma data model can serve a whole family of workbooks instead of producing N near-duplicate DMs. looker-to-sigma consumes that plan in batch mode and runs the conversions concurrently.
Typical flow for a real migration engagement:
looker-assessment against the target instance; review the shortlist with stakeholders.looker-to-sigma and let it work through them.
The following is a "grab bag" of things that might come up during real conversions, with the fix for each.
python3 --version reports 3.9.x and the skill refuses to run:brew install python@3.12) or python.org, then use python3.12 -m pip install explicitly for any helpers. Avoid pip3 as a shorthand — it can quietly resolve back to the old interpreter.looker_api.py whoami returns 401 or Could not authenticate to Looker:~/.looker/looker.ini file is missing or has stale credentials. Re-generate an API3 key under Admin > Users > pick your user > Edit Keys, then update the client_id + client_secret lines in ~/.looker/looker.ini. The base_url must include the API port (:19999) — the customer-facing UI URL won't work for API auth.git pull locally before re-running. The skill reads the *.model.lkml and *.view.lkml files from disk, not from Looker's in-progress dev state.git clone returns Repository not found on a private LookML repo:gh api /user/repository_invitationsgh api -X PATCH /user/repository_invitations/, then retry the clone. If no pending invite shows up, confirm with the repo owner that they invited the same GitHub username you're authenticated as — gh auth status shows your active account.sigma-data-model-mcp). If it isn't installed locally, the skill stops at the gate. Pick option 6. Chat about this and tell Claude:Clone twells89/sigma-data-model-mcp into ~/Desktop/sigma-data-model-mcp for me, then run
npm install && npm run build in that directory. Once the build is done, come back to the gate and pick option 1.(Recommended) option.COPY INTO:Prepare the Demo Data includes the GRANT USAGE and GRANT SELECT statements — if you skipped or modified them, run them now with the role name your Sigma connection actually uses (find it in Sigma under Administration > Connections).sql_distinct_key, merged_results, table calcs — don't have a direct Sigma equivalent. The skill surfaces the original LookML alongside its best-guess Sigma translation. Hand-author the Sigma formula on the affected element using the warehouse-resolved column names.Bash command — Contains shell syntax that cannot be statically analyzed — Do you want to proceed? prompts during the run:eval "$(...)" patterns to inject tokens dynamically. Claude Code's safety analyzer can't pattern-match these for blanket approval even in accept-edits mode. Click 1. Yes on each — it's expected behavior, not a misconfiguration. After the run, you can use the /fewer-permission-prompts skill to scan the transcript and add those patterns to your .claude/settings.local.json so subsequent runs are silent.sql_table_name reference. The skill's verification phase surfaces the specific column in the error — adjust the warehouse table's column names or correct the LookML view before re-running.
What you built is less a single conversion and more a repeatable migration path. The skill took a Looker dashboard — LookML model, view definitions, tile layout, measure expressions — and produced a Sigma data model, a workbook, and a parity report against the live warehouse, all from a single structured prompt. No one rebuilt the dashboard by hand, and the parity numbers are evidence rather than hope.
The patterns worth carrying into your next migration:
looker-assessment scopes and prioritizes the instance; looker-to-sigma converts and verifies. The same shape applies whether you're migrating one dashboard or every dashboard reading from a shared explore.setup.rb has captured your Sigma credentials, the entire migration is one paste. The kickoff prompt reads the LookML directory + dashboard ID + warehouse coordinates + options in one shot, and the skill walks through every phase end-to-end without further interaction unless a gate genuinely needs your call.Prepare the Demo Data transfers to any warehouse Sigma can reach. For dashboards backed by PDTs or Looker-internal data, materialize those upstream and the same pattern applies.A first-pass conversion produces a working starting point and a documented punch list, not a hand-polished workbook. The polish loop is short, and you know exactly what to look at. That's the migration approach you can scale across an entire Looker instance.
Additional Resource Links
Blog
Community
Help Center
QuickStarts
Be sure to check out all the latest developments at Sigma's First Friday Feature page!
