Import from Looker¶
Looker is a great partner to dbt, and this importer is not meant to replace it. It keeps a copy of your Looker work in dbt Charts' open format, in git next to your dbt project, so CI can catch model changes that would break it, lineage covers it, and AI agents can read exactly what it computes. See Why import.
This walkthrough moves one Looker dashboard into a dbt Charts board. It takes about five minutes to fetch, then the agent does the rest. Read Import from other BI tools first for the overall flow.
1. Create a Looker API key¶
- In Looker, open your account page (
https://<your instance>/account). - Under API Keys, choose New API Key. If the section is missing, a Looker admin needs to enable API keys for your user or role.
- Copy the Client ID and Client Secret.
The key acts as you, so it sees exactly the dashboards you can see. The importer changes nothing in Looker: it fetches the dashboard and its SQL, runs each single-value tile's query to record its current value, and asks Looker for a render.
Put the key in your gitignored .env:
2. Find the API address¶
The importer talks to Looker's API, which often listens on a different port
from the web UI (commonly :19999 on self-hosted and older instances; :443
on most newer ones). If the URL you browse to works for the API, nothing more is
needed. If the import fails to connect, set the API origin explicitly:
--base-url on the command line does the same for one run.
3. Import the dashboard¶
Copy the dashboard's URL from your browser and run:
A bare id works when LOOKER_BASE_URL is set:
The command writes ./looker-42/ and prints Wrote looker-42. Start with
outline.md. Use --out for another folder and --force to refresh a bundle
you already fetched.
What you get¶
| Path | From Looker |
|---|---|
dashboard.json |
The dashboard definition from Looker API 4.0 |
outline.md |
Tiles in layout order, with fields, filters, and visualization options |
queries/ |
The SQL Looker generates for each tile, including tiles that point at a saved Look |
kpi/ |
The current value of each single-value tile |
png/dashboard.png |
Looker's own render of the dashboard |
source.json |
The fetch record, plus the timezones the queries run in (query_timezones) |
Some things Looker cannot hand over are noted in outline.md instead of
failing the import: a Look or merged-results tile it cannot fetch, or the value
of a merged single-value tile (the API cannot run merged queries), is noted on
that tile's line, and a failed render is listed under Not fetched. A render
that does not finish in time fails the import; rerun it.
4. Migrate it¶
In your agent, from the project root:
The agent asks whether to keep Looker's SQL verbatim or rewrite each query over
your dbt models, builds the board, and ends with a parity table comparing every
headline number to kpi/. See Migrate the bundle
for what to expect.
Looker-specific notes¶
- LookML is not copied. The bundle carries the SQL Looker compiled, not your LookML. Measures, joins, and access filters show up as SQL; in clean mode the agent re-expresses them over your dbt models.
- Dashboard filters become variables. Each filter, its default, and the tiles it listens to are in the outline, and the board gets a matching control.
- Timezones matter for parity. If Looker converts timestamps, the
timezones are listed in
source.json; a date-bucketed number that is off by a day usually traces back to this.
Troubleshooting¶
| Message | Fix |
|---|---|
LOOKER_CLIENT_ID ... is not set |
Load your .env in the same command, as in step 3 |
| Connection refused or timed out | Set LOOKER_BASE_URL to the API port (step 2) |
... is not empty; pass --force to replace it |
You already have a bundle there; add --force to refetch |
Looker render task ... did not finish in time |
Looker was slow to render; rerun the import. A render that fails outright is listed under Not fetched instead, and the bundle is still usable |