Skip to content

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

  1. In Looker, open your account page (https://<your instance>/account).
  2. 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.
  3. 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:

LOOKER_CLIENT_ID='...'
LOOKER_CLIENT_SECRET='...'

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:

LOOKER_BASE_URL='https://acme.looker.com:19999'

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

set -a; . ./.env; set +a; dct import looker https://acme.looker.com/dashboards/42

A bare id works when LOOKER_BASE_URL is set:

dct import looker 42

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:

Migrate ./looker-42 into a dbt Charts board.

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